Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions TestPrograms/transpiler_example.wfl
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Example WFL program to demonstrate the JavaScript transpiler
// Run: wfl --transpile TestPrograms/transpiler_example.wfl

display "=== WFL to JavaScript Transpiler Demo ==="
display ""

// Variable declarations
store greeting as "Hello"
store counter as 0
store is_active as yes

// Action (function) definition
define action called add_numbers with parameters a and b:
return a plus b
end action

// Action with display
define action called greet_user with parameter name:
display "Welcome, " with name with "!"
end action

// Main entry point
define action called main:
display "Starting program..."

// Using variables
display "Greeting: " with greeting
display "Counter: " with counter
display "Active: " with is_active

// Calling actions
store result as add_numbers with 5 and 10
display "5 + 10 = " with result

greet_user with "Alice"

// Conditional logic
check if is_active:
display "System is active"
otherwise:
display "System is inactive"
end check

// Count loop
display "Counting from 1 to 5:"
count from 1 to 5:
display " Count: " with count
end count

// List operations
create list colors:
add "red"
add "green"
add "blue"
end list

display "Colors:"
for each color in colors:
display " - " with color
end for

// Nested conditions
store score as 85
check if score is greater than 90:
display "Grade: A"
otherwise:
check if score is greater than 80:
display "Grade: B"
otherwise:
display "Grade: C"
end check
end check

display ""
display "=== Demo Complete ==="
end action
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub mod parser;
pub mod pattern;
pub mod repl;
pub mod stdlib;
pub mod transpiler;
pub mod typechecker;
pub mod version;
pub mod wfl_config;
Expand Down
143 changes: 143 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use wfl::lexer::lex_wfl_with_positions;
use wfl::linter::Linter;
use wfl::parser::Parser;
use wfl::repl;
use wfl::transpiler::{TranspilerConfig, TranspilerTarget};
use wfl::typechecker::TypeChecker;
use wfl::wfl_config;
use wfl::{error, exec_trace, info};
Expand Down Expand Up @@ -41,6 +42,13 @@ fn print_help() {
println!(" --time Measure and display execution time");
println!(" --test Run file in test mode");
println!();
println!("TRANSPILATION:");
println!(" --transpile Transpile WFL code to JavaScript");
println!(" --target <env> Target environment: node (default), browser, universal");
println!(" --output <file> Output file (default: <input>.js)");
println!(" --no-runtime Don't include WFL runtime in output");
println!(" --es-modules Generate ES modules (export/import)");
println!();
println!("Configuration Maintenance:");
println!(" --configCheck Check configuration files for issues");
println!(" --configFix Check and fix configuration files");
Expand Down Expand Up @@ -98,6 +106,10 @@ async fn main() -> io::Result<()> {
let mut dump_env_mode = false;
let mut output_path = None;
let mut time_mode = false;
let mut transpile_mode = false;
let mut transpile_target = TranspilerTarget::Node;
let mut transpile_no_runtime = false;
let mut transpile_es_modules = false;
let mut test_mode = false;
let mut file_path = String::new();

Expand Down Expand Up @@ -276,6 +288,64 @@ async fn main() -> io::Result<()> {
time_mode = true;
i += 1;
}
"--transpile" => {
if lint_mode || analyze_mode || fix_mode || config_check_mode || config_fix_mode {
eprintln!(
"Error: --transpile cannot be combined with --lint, --analyze, --fix, --configCheck, or --configFix"
);
process::exit(2);
}
transpile_mode = true;
i += 1;
// Parse transpile options
while i < args.len() && args[i].starts_with("--") {
match args[i].as_str() {
"--target" => {
if i + 1 < args.len() {
transpile_target = match args[i + 1].as_str() {
"node" => TranspilerTarget::Node,
"browser" => TranspilerTarget::Browser,
"universal" => TranspilerTarget::Universal,
_ => {
eprintln!(
"Error: Unknown transpile target '{}'. Use: node, browser, or universal",
args[i + 1]
);
process::exit(2);
}
};
i += 2;
} else {
eprintln!("Error: --target requires an argument");
process::exit(2);
}
}
"--no-runtime" => {
transpile_no_runtime = true;
i += 1;
}
"--es-modules" => {
transpile_es_modules = true;
i += 1;
}
"--output" => {
if i + 1 < args.len() && !args[i + 1].starts_with("--") {
output_path = Some(args[i + 1].clone());
i += 2;
} else {
eprintln!("Error: --output requires a file path");
process::exit(2);
}
}
_ => break,
}
}
// Get input file if not already set
if i < args.len() && !args[i].starts_with("--") && file_path.is_empty() {
file_path = args[i].clone();
i += 1;
}
}
"--test" => {
if lint_mode || analyze_mode || fix_mode || config_check_mode || config_fix_mode {
eprintln!(
Expand Down Expand Up @@ -575,6 +645,79 @@ async fn main() -> io::Result<()> {
}
}

// Handle transpile mode
if transpile_mode {
let tokens_with_pos = lex_wfl_with_positions(&input);
match Parser::new(&tokens_with_pos).parse() {
Ok(program) => {
// Configure the transpiler
let transpiler_config = TranspilerConfig {
include_runtime: !transpile_no_runtime,
source_maps: false,
target: transpile_target,
minify: false,
indent: " ".to_string(),
es_modules: transpile_es_modules,
};

// Run the transpiler
match wfl::transpiler::transpile(&program, &transpiler_config) {
Ok(result) => {
// Show warnings if any
for warning in &result.warnings {
eprintln!(
"Warning at line {}, column {}: {}",
warning.line, warning.column, warning.message
);
}

// Determine output path
let output_file = output_path.unwrap_or_else(|| {
let base = Path::new(&file_path);
let stem = base.file_stem().unwrap_or_default().to_string_lossy();
format!("{}.js", stem)
});

// Write output
if let Err(e) = fs::write(&output_file, &result.code) {
eprintln!("Error writing output file: {e}");

Copilot AI Jan 15, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error message lacks context about which file failed to write. Include the output_file path to help users identify the problem.

Suggested change
eprintln!("Error writing output file: {e}");
eprintln!("Error writing output file '{output_file}': {e}");

Copilot uses AI. Check for mistakes.
process::exit(1);
}

println!("Transpiled to: {output_file}");
if !result.warnings.is_empty() {
println!(" ({} warnings)", result.warnings.len());
}
process::exit(0);
}
Err(e) => {
eprintln!(
"Transpilation error at line {}, column {}: {}",
e.line, e.column, e.message
);
process::exit(1);
}
}
}
Err(errors) => {
eprintln!("Parse errors:");

let mut reporter = DiagnosticReporter::new();
let file_id = reporter.add_file(&file_path, &input);

for error in errors {
let diagnostic = reporter.convert_parse_error(file_id, &error);
if let Err(e) = reporter.report_diagnostic(file_id, &diagnostic) {
eprintln!("Error displaying diagnostic: {e}");
eprintln!("Error: {error}");
}
}

process::exit(2);
}
}
}

if lint_mode {
let tokens_with_pos = lex_wfl_with_positions(&input);
match Parser::new(&tokens_with_pos).parse() {
Expand Down
Loading