diff --git a/compiler/src/lib.rs b/compiler/src/lib.rs index d09edd2a279a2ed694d425f1b0f2f7acf6d3a8d9..620f35e5419e15c1ef1aff95a41adf78f40590a9 100644 --- a/compiler/src/lib.rs +++ b/compiler/src/lib.rs @@ -2,7 +2,7 @@ use miette::Result; pub mod ast; pub mod tokenizer; -pub mod walker; +pub mod printer; pub mod util; @@ -14,7 +14,7 @@ pub fn transpile(content: String) -> Result { // 3. Type check the AST // type_check(tree.clone())?; // 4. Transpile the AST into javascript - let result = walker::transpile(tree)?; + let result = printer::transpile(tree)?; // 5. Return the javascript return Ok(result); } diff --git a/compiler/src/printer/mod.rs b/compiler/src/printer/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..fb310f0a88210c1429169a2f1149e4f70c386ec0 --- /dev/null +++ b/compiler/src/printer/mod.rs @@ -0,0 +1,139 @@ +use miette::Result; + +use super::ast::{Ast, Type}; + +fn transpile_helper(tree: &Ast) -> Result { + Ok(match tree { + Ast::Number(number) => format!("{}", number), + Ast::Identifier(name) => format!("{}", name), + Ast::Bool(value) => format!("{}", value), + Ast::String(value) => format!("\"{}\"", value), + Ast::Comment(comment) => format!("// {}\n", comment), + Ast::DocComment(comment) => format!("/** {} */\n", comment), + Ast::Operation { + operator, + left, + right, + } => format!( + "{} {} {}", + transpile_helper(left)?, + operator.clone().to_string(), + transpile_helper(right)? + ), + Ast::Public { value } => format!("export {}", transpile_helper(value)?), + Ast::VariableDeclaration { + name, + return_type, + value, + } => match return_type { + Type::Bigint => format!("let {} = BigInt({});\n", name, transpile_helper(value)?), + _ => format!("let {} = {};\n", name, transpile_helper(value)?), + }, + Ast::ConstantDeclaration { + name, + return_type, + value, + } => match return_type { + Type::Bigint => format!("const {} = BigInt({});\n", name, transpile_helper(value)?), + _ => format!("const {} = {};\n", name, transpile_helper(value)?), + }, + Ast::Return { return_value } => format!("return {};\n", transpile_helper(return_value)?), + Ast::Function { + name, + arguments, + return_type: _, + block, + } => { + let mut result = format!("function {}(", name); + + for (i, argument) in arguments.iter().enumerate() { + if i == 0 { + result += argument.name.as_str(); + } else { + result += format!(", {}", argument.name).as_str(); + } + } + + result += ") {\n"; + + for (i, statement) in block.value.iter().enumerate() { + if block.implicit_return && i == block.value.len() - 1 { + result += format!("return {};\n", transpile_helper(statement)?).as_str(); + break; + } + result += transpile_helper(statement)?.as_str(); + } + + result += "}\n"; + + result + } + Ast::If { + condition, + value, + else_value, + } => { + let mut result = format!("if ({}) {{\n", transpile_helper(condition)?,); + + for (i, statement) in value.value.iter().enumerate() { + if value.implicit_return && i == value.value.len() - 1 { + result += format!("return {};\n", transpile_helper(statement)?).as_str(); + break; + } + result += transpile_helper(statement)?.as_str(); + } + + result += "}"; + + if let Some(val) = else_value { + result += format!(" else {{\n{}}}", transpile_helper(val)?).as_str(); + } else { + result += "\n"; + } + + result + } + Ast::FunctionCall { name, arguments } => { + let mut result = match name.as_str() { + "print" => String::from("console.log("), + _ => format!("{}(", name), + }; + + for (i, argument) in arguments.iter().enumerate() { + if i == 0 { + result += transpile_helper(argument)?.as_str(); + } else { + result += format!(", {}", transpile_helper(argument)?).as_str(); + } + } + + result += ")"; + + result + } + Ast::Block(block) => { + let mut result = String::from("(()=>{\n"); + for (i, statement) in block.value.iter().enumerate() { + if block.implicit_return && i == block.value.len() - 1 { + result += format!("return {};\n", transpile_helper(statement)?).as_str(); + break; + } + result += transpile_helper(statement)?.as_str(); + } + + result += "})()\n"; + + result + } + }) +} + +pub fn transpile(forest: Vec) -> Result { + let mut result = String::new(); + + for tree in forest { + result.push_str(&transpile_helper(&tree)?); + } + + Ok(result) +} diff --git a/compiler/src/walker.rs b/compiler/src/walker.rs deleted file mode 100644 index fb310f0a88210c1429169a2f1149e4f70c386ec0..0000000000000000000000000000000000000000 --- a/compiler/src/walker.rs +++ /dev/null @@ -1,139 +0,0 @@ -use miette::Result; - -use super::ast::{Ast, Type}; - -fn transpile_helper(tree: &Ast) -> Result { - Ok(match tree { - Ast::Number(number) => format!("{}", number), - Ast::Identifier(name) => format!("{}", name), - Ast::Bool(value) => format!("{}", value), - Ast::String(value) => format!("\"{}\"", value), - Ast::Comment(comment) => format!("// {}\n", comment), - Ast::DocComment(comment) => format!("/** {} */\n", comment), - Ast::Operation { - operator, - left, - right, - } => format!( - "{} {} {}", - transpile_helper(left)?, - operator.clone().to_string(), - transpile_helper(right)? - ), - Ast::Public { value } => format!("export {}", transpile_helper(value)?), - Ast::VariableDeclaration { - name, - return_type, - value, - } => match return_type { - Type::Bigint => format!("let {} = BigInt({});\n", name, transpile_helper(value)?), - _ => format!("let {} = {};\n", name, transpile_helper(value)?), - }, - Ast::ConstantDeclaration { - name, - return_type, - value, - } => match return_type { - Type::Bigint => format!("const {} = BigInt({});\n", name, transpile_helper(value)?), - _ => format!("const {} = {};\n", name, transpile_helper(value)?), - }, - Ast::Return { return_value } => format!("return {};\n", transpile_helper(return_value)?), - Ast::Function { - name, - arguments, - return_type: _, - block, - } => { - let mut result = format!("function {}(", name); - - for (i, argument) in arguments.iter().enumerate() { - if i == 0 { - result += argument.name.as_str(); - } else { - result += format!(", {}", argument.name).as_str(); - } - } - - result += ") {\n"; - - for (i, statement) in block.value.iter().enumerate() { - if block.implicit_return && i == block.value.len() - 1 { - result += format!("return {};\n", transpile_helper(statement)?).as_str(); - break; - } - result += transpile_helper(statement)?.as_str(); - } - - result += "}\n"; - - result - } - Ast::If { - condition, - value, - else_value, - } => { - let mut result = format!("if ({}) {{\n", transpile_helper(condition)?,); - - for (i, statement) in value.value.iter().enumerate() { - if value.implicit_return && i == value.value.len() - 1 { - result += format!("return {};\n", transpile_helper(statement)?).as_str(); - break; - } - result += transpile_helper(statement)?.as_str(); - } - - result += "}"; - - if let Some(val) = else_value { - result += format!(" else {{\n{}}}", transpile_helper(val)?).as_str(); - } else { - result += "\n"; - } - - result - } - Ast::FunctionCall { name, arguments } => { - let mut result = match name.as_str() { - "print" => String::from("console.log("), - _ => format!("{}(", name), - }; - - for (i, argument) in arguments.iter().enumerate() { - if i == 0 { - result += transpile_helper(argument)?.as_str(); - } else { - result += format!(", {}", transpile_helper(argument)?).as_str(); - } - } - - result += ")"; - - result - } - Ast::Block(block) => { - let mut result = String::from("(()=>{\n"); - for (i, statement) in block.value.iter().enumerate() { - if block.implicit_return && i == block.value.len() - 1 { - result += format!("return {};\n", transpile_helper(statement)?).as_str(); - break; - } - result += transpile_helper(statement)?.as_str(); - } - - result += "})()\n"; - - result - } - }) -} - -pub fn transpile(forest: Vec) -> Result { - let mut result = String::new(); - - for tree in forest { - result.push_str(&transpile_helper(&tree)?); - } - - Ok(result) -}