authorgravatar for 11367844+lino-levan@users.noreply.github.comLino Le Van <11367844+lino-levan@users.noreply.github.com> 2024-01-16 13:23:32-08:00
committergravatar for 11367844+lino-levan@users.noreply.github.comLino Le Van <11367844+lino-levan@users.noreply.github.com> 2024-01-16 13:23:32-08:00
loge909581f4c8edf90471d89f9cce5abd05a457a46
tree91283acb578d6f39c8d44aa9ef40f98171667dc1
parent266f616b552eb86530ed664e44aea026cb5820db

feat: add blocks


7 files changed, 136 insertions(+), 20 deletions(-)

compiler/src/ast/mod.rs+61-16
......@@ -8,12 +8,21 @@ use super::tokenizer::Token;
88use error::AstError;
99use types::{Argument, ParserContext};
1010
11pub use types::{Ast, Type};
11pub use types::{Ast, Block, Type};
1212
1313fn parse_expression(tokens: &mut ParserContext) -> Result<Ast> {
1414 let left = match tokens.next() {
1515 Some(token) => match token {
1616 Token::Number(number) => Ast::Number(number.clone()),
17 Token::String(string) => Ast::String(string.clone()),
18 Token::True => Ast::Bool(true),
19 Token::False => Ast::Bool(false),
20 Token::OpenBracket => {
21 // FRICK we consumed the open bracket
22 // we need to put the cursor back
23 tokens.cursor -= 1;
24 Ast::Block(parse_block(tokens)?)
25 }
1726 Token::Identifier(name) => match tokens.peek() {
1827 Some(Token::OpenParanthesis) => {
1928 tokens.next();
......@@ -74,12 +83,60 @@ fn parse_expression(tokens: &mut ParserContext) -> Result<Ast> {
7483 Ok(left)
7584}
7685
86fn parse_block(tokens: &mut ParserContext) -> Result<Block> {
87 match tokens.next() {
88 Some(Token::OpenBracket) => (),
89 _ => return Err(AstError::new("Expected { when parsing block").into()),
90 }
91
92 let mut value = Vec::new();
93 let mut implicit_return = false;
94
95 loop {
96 match tokens.peek() {
97 Some(Token::ClosedBracket) => {
98 tokens.next();
99 break;
100 }
101 _ => (),
102 }
103
104 let current_cursor = tokens.cursor;
105 let result = parse_statement(tokens);
106
107 match result {
108 Ok(ast) => value.push(ast),
109 Err(_) => {
110 tokens.cursor = current_cursor;
111 value.push(parse_expression(tokens)?);
112 implicit_return = true;
113 match tokens.peek() {
114 Some(Token::ClosedBracket) => (),
115 _ => {
116 return Err(AstError::new(
117 "Expected closed bracket after expression in function body",
118 )
119 .into());
120 }
121 }
122 }
123 }
124 }
125
126 Ok(Block {
127 value,
128 implicit_return,
129 })
130}
131
77132fn parse_type(tokens: &mut ParserContext) -> Result<Type> {
78133 match tokens.next() {
79134 Some(Token::Identifier(typ)) => match typ.as_str() {
80135 "int" => Ok(Type::Int),
81136 "float" => Ok(Type::Float),
82137 "bigint" => Ok(Type::Bigint),
138 "bool" => Ok(Type::Bool),
139 "string" => Ok(Type::String),
83140 _ => return Err(AstError::new("Expected type").into()),
84141 },
85142 _ => return Err(AstError::new("Expected type").into()),
......@@ -233,7 +290,7 @@ fn parse_statement(tokens: &mut ParserContext) -> Result<Ast> {
233290 }
234291 };
235292
236 match tokens.next() {
293 match tokens.peek() {
237294 Some(Token::OpenBracket) => (),
238295 _ => {
239296 return Err(AstError::new(
......@@ -243,25 +300,13 @@ fn parse_statement(tokens: &mut ParserContext) -> Result<Ast> {
243300 }
244301 };
245302
246 let mut value = Vec::new();
247
248 loop {
249 match tokens.peek() {
250 Some(Token::ClosedBracket) => {
251 tokens.next();
252 break;
253 }
254 _ => (),
255 }
256
257 value.push(parse_statement(tokens)?);
258 }
303 let block = parse_block(tokens)?;
259304
260305 return Ok(Ast::Function {
261306 name,
262307 arguments,
263308 return_type,
264 value,
309 block
265310 });
266311 }
267312 Token::Identifier(name) => match tokens.peek() {
compiler/src/ast/types.rs+14-1
......@@ -1,3 +1,5 @@
1// TODO(lino-levan): Split up AST into expressions, statements, etc.
2
13use crate::tokenizer::Token;
24use crate::util::Operator;
35
......@@ -40,6 +42,14 @@ pub enum Type {
4042 Int,
4143 Float,
4244 Bigint,
45 Bool,
46 String,
47}
48
49#[derive(Debug)]
50pub struct Block {
51 pub value: Vec<Ast>,
52 pub implicit_return: bool,
4353}
4454
4555#[derive(Debug)]
......@@ -75,13 +85,16 @@ pub enum Ast {
7585 name: String,
7686 arguments: Vec<Argument>,
7787 return_type: Type,
78 value: Vec<Ast>,
88 block: Block
7989 },
8090 FunctionCall {
8191 name: String,
8292 arguments: Vec<Ast>,
8393 },
94 Block(Block),
8495 Number(String),
96 Bool(bool),
97 String(String),
8598 Identifier(String),
8699 Comment(String),
87100 DocComment(String),
compiler/src/tokenizer.rs+24
......@@ -15,12 +15,17 @@ pub enum Token {
1515 // Literals
1616 Identifier(String),
1717 Number(String),
18 String(String),
1819 // Comments
1920 Comment(String),
2021 DocComment(String),
2122 // Keywords
23 True,
24 False,
2225 Let,
2326 Var,
27 If,
28 Else,
2429 Return,
2530 Pub,
2631 Function,
......@@ -65,12 +70,31 @@ pub fn tokenize(content: String) -> Result<Vec<Token>> {
6570 match current_token.as_str() {
6671 "var" => tokens.push(Token::Var),
6772 "let" => tokens.push(Token::Let),
73 "if" => tokens.push(Token::If),
74 "else" => tokens.push(Token::Else),
6875 "pub" => tokens.push(Token::Pub),
6976 "fn" => tokens.push(Token::Function),
7077 "return" => tokens.push(Token::Return),
78 "true" => tokens.push(Token::True),
79 "false" => tokens.push(Token::False),
7180 _ => tokens.push(Token::Identifier(current_token)),
7281 }
7382 }
83 '"' => {
84 let mut current_token = String::new();
85 loop {
86 let c = chars.next();
87 if c.is_none() {
88 break;
89 }
90 let (_, c) = c.unwrap();
91 match c {
92 '"' => break,
93 _ => current_token.push(c),
94 }
95 }
96 tokens.push(Token::String(current_token));
97 }
7498 '0'..='9' => {
7599 let mut current_token = String::new();
76100 current_token.push(c);
compiler/src/walker.rs+22-2
......@@ -6,6 +6,8 @@ fn transpile_helper(tree: &Ast) -> Result<String> {
66 Ok(match tree {
77 Ast::Number(number) => format!("{}", number),
88 Ast::Identifier(name) => format!("{}", name),
9 Ast::Bool(value) => format!("{}", value),
10 Ast::String(value) => format!("\"{}\"", value),
911 Ast::Comment(comment) => format!("// {}\n", comment),
1012 Ast::DocComment(comment) => format!("/** {} */\n", comment),
1113 Ast::Operation {
......@@ -40,7 +42,7 @@ fn transpile_helper(tree: &Ast) -> Result<String> {
4042 name,
4143 arguments,
4244 return_type: _,
43 value,
45 block
4446 } => {
4547 let mut result = format!("function {}(", name);
4648
......@@ -54,7 +56,11 @@ fn transpile_helper(tree: &Ast) -> Result<String> {
5456
5557 result += ") {\n";
5658
57 for statement in value {
59 for (i, statement) in block.value.iter().enumerate() {
60 if block.implicit_return && i == block.value.len() - 1 {
61 result += format!("return {};\n", transpile_helper(statement)?).as_str();
62 break;
63 }
5864 result += transpile_helper(statement)?.as_str();
5965 }
6066
......@@ -78,6 +84,20 @@ fn transpile_helper(tree: &Ast) -> Result<String> {
7884
7985 result += ")";
8086
87 result
88 }
89 Ast::Block(block) => {
90 let mut result = String::from("(()=>{");
91 for (i, statement) in block.value.iter().enumerate() {
92 if block.implicit_return && i == block.value.len() - 1 {
93 result += format!("return {};\n", transpile_helper(statement)?).as_str();
94 break;
95 }
96 result += transpile_helper(statement)?.as_str();
97 }
98
99 result += "})()\n";
100
81101 result
82102 }
83103 })
examples/basics/control.blight+4
......@@ -1 +1,5 @@
1let x: bool = true;
12
3if x {
4 print("x is true!");
5}
examples/basics/expressions.blight created+10
......@@ -0,0 +1,10 @@
1// everything is an expression in blight
2// everything.
3// hehe
4
5let x: int = 5 + {
6 let y: int = 5;
7 y
8};
9
10print(x); // 10
examples/basics/functions.blight+1-1
......@@ -1,5 +1,5 @@
11fn bingus(x: int, y: int) -> int {
2 return x * y;
2 x * y
33}
44
55let result: int = bingus(10, 25);