| author | |
| committer | |
| log | 6c14072860c381a177f886b7c3f00001fafd9abc |
| tree | ce847a8d38b134e2a3e349ddc141dc98eb7c2618 |
| parent | de824b0e32bfb81f03869727ac3ff2006a3492e9 |
9 files changed, 177 insertions(+), 135 deletions(-)
examples/easy.blight deleted-7| ... | @@ -1,7 +0,0 @@ | ||
| 1 | var x: int = 0; | ||
| 2 | var y: float = 0; | ||
| 3 | var z: bigint = 0; | ||
| 4 | |||
| 5 | let a: int = 0; | ||
| 6 | let b: float = 0; | ||
| 7 | let c: bigint = 0; | ||
examples/operations.blight created+1| ... | @@ -0,0 +1 @@ | ||
| 1 | let a: int = 10 - 2 / 4 * 15; | ||
examples/variables.blight created+7| ... | @@ -0,0 +1,7 @@ | ||
| 1 | var x: int = 0; | ||
| 2 | var y: float = 0; | ||
| 3 | var z: bigint = 0; | ||
| 4 | |||
| 5 | let a: int = 0; | ||
| 6 | let b: float = 0; | ||
| 7 | let c: bigint = 0; | ||
src/main.rs+2-2| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | use std::path::PathBuf; | 1 | use std::path::PathBuf; |
| 2 | 2 | ||
| 3 | use miette::{Result, NamedSource}; | ||
| 4 | use clap::{Parser, Subcommand}; | 3 | use clap::{Parser, Subcommand}; |
| 4 | use miette::Result; | ||
| 5 | 5 | ||
| 6 | mod transpile; | 6 | mod transpile; |
| 7 | 7 | ||
| ... | @@ -21,7 +21,7 @@ enum Commands { | ... | @@ -21,7 +21,7 @@ enum Commands { |
| 21 | /// Compiles a file into javascript | 21 | /// Compiles a file into javascript |
| 22 | Compile { | 22 | Compile { |
| 23 | /// lists test values | 23 | /// lists test values |
| 24 | file: PathBuf | 24 | file: PathBuf, |
| 25 | }, | 25 | }, |
| 26 | } | 26 | } |
| 27 | 27 |
src/transpile/ast.rs+71-50| ... | @@ -1,19 +1,21 @@ | ... | @@ -1,19 +1,21 @@ |
| 1 | use miette::{Result, Diagnostic}; | 1 | use miette::{Diagnostic, Result}; |
| 2 | use thiserror::Error; | 2 | use thiserror::Error; |
| 3 | 3 | ||
| 4 | use super::tokenizer::Token; | 4 | use super::tokenizer::Token; |
| 5 | use super::util::PeekableIterator; | 5 | use super::util::{Operator, PeekableIterator}; |
| 6 | 6 | ||
| 7 | #[derive(Error, Diagnostic, Debug)] | 7 | #[derive(Error, Diagnostic, Debug)] |
| 8 | #[error("AstError")] | 8 | #[error("AstError")] |
| 9 | struct AstError { | 9 | struct AstError { |
| 10 | #[help] | 10 | #[help] |
| 11 | error: String | 11 | error: String, |
| 12 | } | 12 | } |
| 13 | 13 | ||
| 14 | impl AstError { | 14 | impl AstError { |
| 15 | fn new(error: &'static str) -> AstError { | 15 | fn new(error: &'static str) -> AstError { |
| 16 | AstError { error: String::from(error) } | 16 | AstError { |
| 17 | error: String::from(error), | ||
| 18 | } | ||
| 17 | } | 19 | } |
| 18 | } | 20 | } |
| 19 | 21 | ||
| ... | @@ -21,7 +23,7 @@ impl AstError { | ... | @@ -21,7 +23,7 @@ impl AstError { |
| 21 | pub enum Type { | 23 | pub enum Type { |
| 22 | Int, | 24 | Int, |
| 23 | Float, | 25 | Float, |
| 24 | Bigint | 26 | Bigint, |
| 25 | } | 27 | } |
| 26 | 28 | ||
| 27 | #[derive(Debug)] | 29 | #[derive(Debug)] |
| ... | @@ -29,107 +31,126 @@ pub enum Ast { | ... | @@ -29,107 +31,126 @@ pub enum Ast { |
| 29 | ConstantDeclaration { | 31 | ConstantDeclaration { |
| 30 | name: String, | 32 | name: String, |
| 31 | typ: Type, | 33 | typ: Type, |
| 32 | value: Box<Ast> | 34 | value: Box<Ast>, |
| 33 | }, | 35 | }, |
| 34 | VariableDeclaration { | 36 | VariableDeclaration { |
| 35 | name: String, | 37 | name: String, |
| 36 | typ: Type, | 38 | typ: Type, |
| 37 | value: Box<Ast> | 39 | value: Box<Ast>, |
| 40 | }, | ||
| 41 | Operation { | ||
| 42 | operator: Operator, | ||
| 43 | left: Box<Ast>, | ||
| 44 | right: Box<Ast>, | ||
| 38 | }, | 45 | }, |
| 39 | Number(String), | 46 | Number(String), |
| 40 | } | 47 | } |
| 41 | 48 | ||
| 42 | fn parse_expression(tokens: &mut dyn PeekableIterator<Item=&Token>) -> Result<Ast> { | 49 | fn parse_expression(tokens: &mut dyn PeekableIterator<Item = &Token>) -> Result<Ast> { |
| 43 | match tokens.next() { | 50 | let left = match tokens.next() { |
| 44 | Some(token) => match token { | 51 | Some(token) => match token { |
| 45 | Token::Number(number) => Token::Number(number.clone()), | 52 | Token::Number(number) => Ast::Number(number.clone()), |
| 46 | _ => return Err(AstError::new("Expected expression, but did not get it").into()) | 53 | _ => return Err(AstError::new("Expected expression, but did not get it").into()), |
| 47 | }, | 54 | }, |
| 48 | None => return Err(AstError::new("Expected expression, but got nothing instead").into()) | 55 | None => return Err(AstError::new("Expected expression, but got nothing instead").into()), |
| 49 | |||
| 50 | }; | 56 | }; |
| 57 | |||
| 58 | match tokens.peek() { | ||
| 59 | Some(token) => match token { | ||
| 60 | Token::Operator(operator) => { | ||
| 61 | tokens.next(); | ||
| 62 | return Ok(Ast::Operation { | ||
| 63 | operator: operator.clone(), | ||
| 64 | left: Box::new(left), | ||
| 65 | right: Box::new(parse_expression(tokens)?), | ||
| 66 | }); | ||
| 67 | } | ||
| 68 | _ => (), | ||
| 69 | }, | ||
| 70 | _ => (), | ||
| 71 | } | ||
| 72 | |||
| 51 | Ok(Ast::Number(String::from("10"))) | 73 | Ok(Ast::Number(String::from("10"))) |
| 52 | } | 74 | } |
| 53 | 75 | ||
| 54 | /// Precondition: There is at least one token in the iterator | 76 | /// Precondition: There is at least one token in the iterator |
| 55 | fn parse_statement(tokens: &mut dyn PeekableIterator<Item=&Token>) -> Result<Ast> { | 77 | fn parse_statement(tokens: &mut dyn PeekableIterator<Item = &Token>) -> Result<Ast> { |
| 56 | match tokens.next().unwrap() { | 78 | match tokens.next().unwrap() { |
| 57 | Token::Let => { | 79 | Token::Let => { |
| 58 | let name = match tokens.next() { | 80 | let name = match tokens.next() { |
| 59 | Some(Token::Identifier(name)) => name, | 81 | Some(Token::Identifier(name)) => name, |
| 60 | _ => return Err(AstError::new("Expected identifier after var").into()) | 82 | _ => return Err(AstError::new("Expected identifier after var").into()), |
| 61 | }; | 83 | }; |
| 62 | let typ = match tokens.next() { | 84 | let typ = match tokens.next() { |
| 63 | Some(Token::Colon) => { | 85 | Some(Token::Colon) => match tokens.next() { |
| 64 | match tokens.next() { | 86 | Some(Token::Identifier(typ)) => match typ.as_str() { |
| 65 | Some(Token::Identifier(typ)) => { | 87 | "int" => Type::Int, |
| 66 | match typ.as_str() { | 88 | "float" => Type::Float, |
| 67 | "int" => Type::Int, | 89 | "bigint" => Type::Bigint, |
| 68 | "float" => Type::Float, | 90 | _ => return Err(AstError::new("Expected type after colon").into()), |
| 69 | "bigint" => Type::Bigint, | 91 | }, |
| 70 | _ => return Err(AstError::new("Expected type after colon").into()) | 92 | _ => return Err(AstError::new("Expected type after colon").into()), |
| 71 | } | ||
| 72 | }, | ||
| 73 | _ => return Err(AstError::new("Expected type after colon").into()) | ||
| 74 | } | ||
| 75 | }, | 93 | }, |
| 76 | _ => return Err(AstError::new("Expected colon after identifier").into()) | 94 | _ => return Err(AstError::new("Expected colon after identifier").into()), |
| 77 | }; | 95 | }; |
| 78 | let value = match tokens.next() { | 96 | let value = match tokens.next() { |
| 79 | Some(Token::Equals) => parse_expression(tokens)?, | 97 | Some(Token::Equals) => parse_expression(tokens)?, |
| 80 | _ => return Err(AstError::new("Expected equals after identifier").into()) | 98 | _ => return Err(AstError::new("Expected equals after identifier").into()), |
| 81 | }; | 99 | }; |
| 82 | match tokens.next() { | 100 | match tokens.next() { |
| 83 | Some(Token::Semicolon) => (), | 101 | Some(Token::Semicolon) => (), |
| 84 | _ => return Err(AstError::new("Expected semicolon after variable declaration").into()) | 102 | _ => { |
| 103 | return Err( | ||
| 104 | AstError::new("Expected semicolon after variable declaration").into(), | ||
| 105 | ) | ||
| 106 | } | ||
| 85 | }; | 107 | }; |
| 86 | Ok(Ast::ConstantDeclaration { | 108 | Ok(Ast::ConstantDeclaration { |
| 87 | name: name.clone(), | 109 | name: name.clone(), |
| 88 | typ, | 110 | typ, |
| 89 | value: Box::new(value), | 111 | value: Box::new(value), |
| 90 | }) | 112 | }) |
| 91 | }, | 113 | } |
| 92 | Token::Var => { | 114 | Token::Var => { |
| 93 | let name = match tokens.next() { | 115 | let name = match tokens.next() { |
| 94 | Some(Token::Identifier(name)) => name, | 116 | Some(Token::Identifier(name)) => name, |
| 95 | _ => return Err(AstError::new("Expected identifier after var").into()) | 117 | _ => return Err(AstError::new("Expected identifier after var").into()), |
| 96 | }; | 118 | }; |
| 97 | let typ = match tokens.next() { | 119 | let typ = match tokens.next() { |
| 98 | Some(Token::Colon) => { | 120 | Some(Token::Colon) => match tokens.next() { |
| 99 | match tokens.next() { | 121 | Some(Token::Identifier(typ)) => match typ.as_str() { |
| 100 | Some(Token::Identifier(typ)) => { | 122 | "int" => Type::Int, |
| 101 | match typ.as_str() { | 123 | "float" => Type::Float, |
| 102 | "int" => Type::Int, | 124 | "bigint" => Type::Bigint, |
| 103 | "float" => Type::Float, | 125 | _ => return Err(AstError::new("Expected type after colon").into()), |
| 104 | "bigint" => Type::Bigint, | 126 | }, |
| 105 | _ => return Err(AstError::new("Expected type after colon").into()) | 127 | _ => return Err(AstError::new("Expected type after colon").into()), |
| 106 | } | ||
| 107 | }, | ||
| 108 | _ => return Err(AstError::new("Expected type after colon").into()) | ||
| 109 | } | ||
| 110 | }, | 128 | }, |
| 111 | _ => return Err(AstError::new("Expected colon after identifier").into()) | 129 | _ => return Err(AstError::new("Expected colon after identifier").into()), |
| 112 | }; | 130 | }; |
| 113 | let value = match tokens.next() { | 131 | let value = match tokens.next() { |
| 114 | Some(Token::Equals) => parse_expression(tokens)?, | 132 | Some(Token::Equals) => parse_expression(tokens)?, |
| 115 | _ => return Err(AstError::new("Expected equals after identifier").into()) | 133 | _ => return Err(AstError::new("Expected equals after identifier").into()), |
| 116 | }; | 134 | }; |
| 117 | match tokens.next() { | 135 | match tokens.next() { |
| 118 | Some(Token::Semicolon) => (), | 136 | Some(Token::Semicolon) => (), |
| 119 | _ => return Err(AstError::new("Expected semicolon after variable declaration").into()) | 137 | _ => { |
| 138 | return Err( | ||
| 139 | AstError::new("Expected semicolon after variable declaration").into(), | ||
| 140 | ) | ||
| 141 | } | ||
| 120 | }; | 142 | }; |
| 121 | Ok(Ast::VariableDeclaration { | 143 | Ok(Ast::VariableDeclaration { |
| 122 | name: name.clone(), | 144 | name: name.clone(), |
| 123 | typ, | 145 | typ, |
| 124 | value: Box::new(value), | 146 | value: Box::new(value), |
| 125 | }) | 147 | }) |
| 126 | }, | 148 | } |
| 127 | Token::Number(number) => Ok(Ast::Number(number.clone())), | 149 | Token::Number(number) => Ok(Ast::Number(number.clone())), |
| 128 | _ => return Err(AstError::new("Unexpected token").into()) | 150 | _ => return Err(AstError::new("Unexpected token").into()), |
| 129 | } | 151 | } |
| 130 | } | 152 | } |
| 131 | 153 | ||
| 132 | |||
| 133 | pub fn parse(tokens: Vec<Token>) -> Result<Vec<Ast>> { | 154 | pub fn parse(tokens: Vec<Token>) -> Result<Vec<Ast>> { |
| 134 | let mut iter = tokens.iter().peekable(); | 155 | let mut iter = tokens.iter().peekable(); |
| 135 | let mut ast: Vec<Ast> = Vec::new(); | 156 | let mut ast: Vec<Ast> = Vec::new(); |
src/transpile/mod.rs+3-3| ... | @@ -1,12 +1,12 @@ | ... | @@ -1,12 +1,12 @@ |
| 1 | use miette::{Result}; | 1 | use miette::Result; |
| 2 | 2 | ||
| 3 | mod tokenizer; | ||
| 4 | mod ast; | 3 | mod ast; |
| 4 | mod tokenizer; | ||
| 5 | mod walker; | 5 | mod walker; |
| 6 | 6 | ||
| 7 | mod util; | 7 | mod util; |
| 8 | 8 | ||
| 9 | pub fn transpile(content: String) -> Result<String> { | 9 | pub fn transpile(content: String) -> Result<String> { |
| 10 | // 1. Tokenize the input | 10 | // 1. Tokenize the input |
| 11 | let tokens = tokenizer::tokenize(content)?; | 11 | let tokens = tokenizer::tokenize(content)?; |
| 12 | // 2. Parse the tokens into an AST | 12 | // 2. Parse the tokens into an AST |
src/transpile/tokenizer.rs+56-61| ... | @@ -1,19 +1,13 @@ | ... | @@ -1,19 +1,13 @@ |
| 1 | use miette::{Result, Diagnostic}; | 1 | use miette::{Diagnostic, Result}; |
| 2 | use thiserror::Error; | 2 | use thiserror::Error; |
| 3 | 3 | ||
| 4 | use super::util::Operator; | ||
| 5 | |||
| 4 | #[derive(Error, Diagnostic, Debug)] | 6 | #[derive(Error, Diagnostic, Debug)] |
| 5 | #[error("UnknownCharacter")] | 7 | #[error("UnknownCharacter")] |
| 6 | struct UnknownCharacter { | 8 | struct UnknownCharacter { |
| 7 | #[help] | 9 | #[help] |
| 8 | error: String | 10 | error: String, |
| 9 | } | ||
| 10 | |||
| 11 | #[derive(Debug, Clone)] | ||
| 12 | pub enum Operator { | ||
| 13 | Add, | ||
| 14 | Substract, | ||
| 15 | Multiply, | ||
| 16 | Divide, | ||
| 17 | } | 11 | } |
| 18 | 12 | ||
| 19 | #[derive(Debug, Clone)] | 13 | #[derive(Debug, Clone)] |
| ... | @@ -28,7 +22,7 @@ pub enum Token { | ... | @@ -28,7 +22,7 @@ pub enum Token { |
| 28 | Equals, | 22 | Equals, |
| 29 | Semicolon, | 23 | Semicolon, |
| 30 | // Operators | 24 | // Operators |
| 31 | Operator(Operator) | 25 | Operator(Operator), |
| 32 | } | 26 | } |
| 33 | 27 | ||
| 34 | pub fn tokenize(content: String) -> Result<Vec<Token>> { | 28 | pub fn tokenize(content: String) -> Result<Vec<Token>> { |
| ... | @@ -37,64 +31,65 @@ pub fn tokenize(content: String) -> Result<Vec<Token>> { | ... | @@ -37,64 +31,65 @@ pub fn tokenize(content: String) -> Result<Vec<Token>> { |
| 37 | 31 | ||
| 38 | loop { | 32 | loop { |
| 39 | match chars.next() { | 33 | match chars.next() { |
| 40 | Some((i, c)) => { | 34 | Some((_, c)) => match c { |
| 41 | match c { | 35 | 'a'..='z' | 'A'..='Z' | '_' => { |
| 42 | 'a'..='z' | 'A'..='Z' | '_' => { | 36 | let mut current_token = String::new(); |
| 43 | let mut current_token = String::new(); | 37 | current_token.push(c); |
| 44 | current_token.push(c); | 38 | loop { |
| 45 | loop { | 39 | let c = chars.peek(); |
| 46 | let c = chars.peek(); | 40 | if c.is_none() { |
| 47 | if c.is_none() { | 41 | break; |
| 48 | break; | 42 | } |
| 49 | } | 43 | let (_, c) = c.unwrap(); |
| 50 | let (_, c) = c.unwrap(); | 44 | match c { |
| 51 | match c { | 45 | 'a'..='z' | 'A'..='Z' | '_' | '0'..='9' => { |
| 52 | 'a'..='z' | 'A'..='Z' | '_' | '0'..='9' => { | 46 | current_token.push(*c); |
| 53 | current_token.push(*c); | 47 | chars.next(); |
| 54 | chars.next(); | ||
| 55 | }, | ||
| 56 | _ => break, | ||
| 57 | } | 48 | } |
| 49 | _ => break, | ||
| 58 | } | 50 | } |
| 51 | } | ||
| 59 | 52 | ||
| 60 | match current_token.as_str() { | 53 | match current_token.as_str() { |
| 61 | "var" => tokens.push(Token::Var), | 54 | "var" => tokens.push(Token::Var), |
| 62 | "let" => tokens.push(Token::Let), | 55 | "let" => tokens.push(Token::Let), |
| 63 | _ => tokens.push(Token::Identifier(current_token)), | 56 | _ => tokens.push(Token::Identifier(current_token)), |
| 57 | } | ||
| 58 | } | ||
| 59 | '0'..='9' => { | ||
| 60 | let mut current_token = String::new(); | ||
| 61 | current_token.push(c); | ||
| 62 | loop { | ||
| 63 | let c = chars.peek(); | ||
| 64 | if c.is_none() { | ||
| 65 | break; | ||
| 64 | } | 66 | } |
| 65 | }, | 67 | let (_, c) = c.unwrap(); |
| 66 | '0'..='9' => { | 68 | match c { |
| 67 | let mut current_token = String::new(); | 69 | '0'..='9' => { |
| 68 | current_token.push(c); | 70 | current_token.push(*c); |
| 69 | loop { | 71 | chars.next(); |
| 70 | let c = chars.peek(); | ||
| 71 | if c.is_none() { | ||
| 72 | break; | ||
| 73 | } | ||
| 74 | let (_, c) = c.unwrap(); | ||
| 75 | match c { | ||
| 76 | '0'..='9' => { | ||
| 77 | current_token.push(*c); | ||
| 78 | chars.next(); | ||
| 79 | }, | ||
| 80 | _ => break, | ||
| 81 | } | 72 | } |
| 73 | _ => break, | ||
| 82 | } | 74 | } |
| 83 | tokens.push(Token::Number(current_token)); | ||
| 84 | }, | ||
| 85 | ':' => tokens.push(Token::Colon), | ||
| 86 | '=' => tokens.push(Token::Equals), | ||
| 87 | ';' => tokens.push(Token::Semicolon), | ||
| 88 | '+' => tokens.push(Token::Operator(Operator::Add)), | ||
| 89 | '-' => tokens.push(Token::Operator(Operator::Substract)), | ||
| 90 | '*' => tokens.push(Token::Operator(Operator::Multiply)), | ||
| 91 | '/' => tokens.push(Token::Operator(Operator::Divide)), | ||
| 92 | s if s.is_whitespace() => (), | ||
| 93 | _ => { | ||
| 94 | return Err(UnknownCharacter { error: format!("Unsupported character: {}", c)}.into()) | ||
| 95 | } | 75 | } |
| 76 | tokens.push(Token::Number(current_token)); | ||
| 77 | } | ||
| 78 | ':' => tokens.push(Token::Colon), | ||
| 79 | '=' => tokens.push(Token::Equals), | ||
| 80 | ';' => tokens.push(Token::Semicolon), | ||
| 81 | '+' => tokens.push(Token::Operator(Operator::Add)), | ||
| 82 | '-' => tokens.push(Token::Operator(Operator::Substract)), | ||
| 83 | '*' => tokens.push(Token::Operator(Operator::Multiply)), | ||
| 84 | '/' => tokens.push(Token::Operator(Operator::Divide)), | ||
| 85 | s if s.is_whitespace() => (), | ||
| 86 | _ => { | ||
| 87 | return Err(UnknownCharacter { | ||
| 88 | error: format!("Unsupported character: {}", c), | ||
| 89 | } | ||
| 90 | .into()) | ||
| 96 | } | 91 | } |
| 97 | } | 92 | }, |
| 98 | None => break, | 93 | None => break, |
| 99 | } | 94 | } |
| 100 | } | 95 | } |
src/transpile/util.rs+20-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // Rust why do you not have a peekable iterator in the standard library? | 1 | // Rust why do you not have a peekable iterator in the standard library? |
| 2 | // Stolen from https://users.rust-lang.org/t/peekable-argument-there-has-to-be-a-simpler-way/6959 | 2 | // Stolen from https://users.rust-lang.org/t/peekable-argument-there-has-to-be-a-simpler-way/6959 |
| 3 | pub trait PeekableIterator : std::iter::Iterator { | 3 | pub trait PeekableIterator: std::iter::Iterator { |
| 4 | fn peek(&mut self) -> Option<&Self::Item>; | 4 | fn peek(&mut self) -> Option<&Self::Item>; |
| 5 | } | 5 | } |
| 6 | 6 | ||
| ... | @@ -9,3 +9,22 @@ impl<I: std::iter::Iterator> PeekableIterator for std::iter::Peekable<I> { | ... | @@ -9,3 +9,22 @@ impl<I: std::iter::Iterator> PeekableIterator for std::iter::Peekable<I> { |
| 9 | std::iter::Peekable::peek(self) | 9 | std::iter::Peekable::peek(self) |
| 10 | } | 10 | } |
| 11 | } | 11 | } |
| 12 | |||
| 13 | #[derive(Debug, Clone)] | ||
| 14 | pub enum Operator { | ||
| 15 | Add, | ||
| 16 | Substract, | ||
| 17 | Multiply, | ||
| 18 | Divide, | ||
| 19 | } | ||
| 20 | |||
| 21 | impl Operator { | ||
| 22 | pub fn to_string(self) -> String { | ||
| 23 | String::from(match self { | ||
| 24 | Self::Add => "+", | ||
| 25 | Self::Substract => "-", | ||
| 26 | Self::Divide => "/", | ||
| 27 | Self::Multiply => "*", | ||
| 28 | }) | ||
| 29 | } | ||
| 30 | } |
src/transpile/walker.rs+17-11| ... | @@ -3,18 +3,24 @@ use super::ast::{Ast, Type}; | ... | @@ -3,18 +3,24 @@ use super::ast::{Ast, Type}; |
| 3 | fn transpile_helper(tree: Ast) -> String { | 3 | fn transpile_helper(tree: Ast) -> String { |
| 4 | match tree { | 4 | match tree { |
| 5 | Ast::Number(number) => format!("{}", number), | 5 | Ast::Number(number) => format!("{}", number), |
| 6 | Ast::VariableDeclaration { name, typ, value } => { | 6 | Ast::Operation { |
| 7 | match typ { | 7 | operator, |
| 8 | Type::Bigint => format!("let {} = BigInt({});\n", name, transpile_helper(*value)), | 8 | left, |
| 9 | _ => format!("let {} = {};\n", name, transpile_helper(*value)) | 9 | right, |
| 10 | } | 10 | } => format!( |
| 11 | "{} {} {}", | ||
| 12 | transpile_helper(*left), | ||
| 13 | operator.to_string(), | ||
| 14 | transpile_helper(*right) | ||
| 15 | ), | ||
| 16 | Ast::VariableDeclaration { name, typ, value } => match typ { | ||
| 17 | Type::Bigint => format!("let {} = BigInt({});\n", name, transpile_helper(*value)), | ||
| 18 | _ => format!("let {} = {};\n", name, transpile_helper(*value)), | ||
| 19 | }, | ||
| 20 | Ast::ConstantDeclaration { name, typ, value } => match typ { | ||
| 21 | Type::Bigint => format!("const {} = BigInt({});\n", name, transpile_helper(*value)), | ||
| 22 | _ => format!("const {} = {};\n", name, transpile_helper(*value)), | ||
| 11 | }, | 23 | }, |
| 12 | Ast::ConstantDeclaration { name, typ, value } => { | ||
| 13 | match typ { | ||
| 14 | Type::Bigint => format!("const {} = BigInt({});\n", name, transpile_helper(*value)), | ||
| 15 | _ => format!("const {} = {};\n", name, transpile_helper(*value)) | ||
| 16 | } | ||
| 17 | } | ||
| 18 | } | 24 | } |
| 19 | } | 25 | } |
| 20 | 26 |