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;...@@ -8,12 +8,21 @@ use super::tokenizer::Token;
8use error::AstError;8use error::AstError;
9use types::{Argument, ParserContext};9use types::{Argument, ParserContext};
1010
11pub use types::{Ast, Type};11pub use types::{Ast, Block, Type};
1212
13fn parse_expression(tokens: &mut ParserContext) -> Result<Ast> {13fn parse_expression(tokens: &mut ParserContext) -> Result<Ast> {
14 let left = match tokens.next() {14 let left = match tokens.next() {
15 Some(token) => match token {15 Some(token) => match token {
16 Token::Number(number) => Ast::Number(number.clone()),16 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 }
17 Token::Identifier(name) => match tokens.peek() {26 Token::Identifier(name) => match tokens.peek() {
18 Some(Token::OpenParanthesis) => {27 Some(Token::OpenParanthesis) => {
19 tokens.next();28 tokens.next();
...@@ -74,12 +83,60 @@ fn parse_expression(tokens: &mut ParserContext) -> Result<Ast> {...@@ -74,12 +83,60 @@ fn parse_expression(tokens: &mut ParserContext) -> Result<Ast> {
74 Ok(left)83 Ok(left)
75}84}
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
77fn parse_type(tokens: &mut ParserContext) -> Result<Type> {132fn parse_type(tokens: &mut ParserContext) -> Result<Type> {
78 match tokens.next() {133 match tokens.next() {
79 Some(Token::Identifier(typ)) => match typ.as_str() {134 Some(Token::Identifier(typ)) => match typ.as_str() {
80 "int" => Ok(Type::Int),135 "int" => Ok(Type::Int),
81 "float" => Ok(Type::Float),136 "float" => Ok(Type::Float),
82 "bigint" => Ok(Type::Bigint),137 "bigint" => Ok(Type::Bigint),
138 "bool" => Ok(Type::Bool),
139 "string" => Ok(Type::String),
83 _ => return Err(AstError::new("Expected type").into()),140 _ => return Err(AstError::new("Expected type").into()),
84 },141 },
85 _ => return Err(AstError::new("Expected type").into()),142 _ => return Err(AstError::new("Expected type").into()),
...@@ -233,7 +290,7 @@ fn parse_statement(tokens: &mut ParserContext) -> Result<Ast> {...@@ -233,7 +290,7 @@ fn parse_statement(tokens: &mut ParserContext) -> Result<Ast> {
233 }290 }
234 };291 };
235292
236 match tokens.next() {293 match tokens.peek() {
237 Some(Token::OpenBracket) => (),294 Some(Token::OpenBracket) => (),
238 _ => {295 _ => {
239 return Err(AstError::new(296 return Err(AstError::new(
...@@ -243,25 +300,13 @@ fn parse_statement(tokens: &mut ParserContext) -> Result<Ast> {...@@ -243,25 +300,13 @@ fn parse_statement(tokens: &mut ParserContext) -> Result<Ast> {
243 }300 }
244 };301 };
245302
246 let mut value = Vec::new();303 let block = parse_block(tokens)?;
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 }
259304
260 return Ok(Ast::Function {305 return Ok(Ast::Function {
261 name,306 name,
262 arguments,307 arguments,
263 return_type,308 return_type,
264 value,309 block
265 });310 });
266 }311 }
267 Token::Identifier(name) => match tokens.peek() {312 Token::Identifier(name) => match tokens.peek() {
compiler/src/ast/types.rs+14-1
...@@ -1,3 +1,5 @@...@@ -1,3 +1,5 @@
1// TODO(lino-levan): Split up AST into expressions, statements, etc.
2
1use crate::tokenizer::Token;3use crate::tokenizer::Token;
2use crate::util::Operator;4use crate::util::Operator;
35
...@@ -40,6 +42,14 @@ pub enum Type {...@@ -40,6 +42,14 @@ pub enum Type {
40 Int,42 Int,
41 Float,43 Float,
42 Bigint,44 Bigint,
45 Bool,
46 String,
47}
48
49#[derive(Debug)]
50pub struct Block {
51 pub value: Vec<Ast>,
52 pub implicit_return: bool,
43}53}
4454
45#[derive(Debug)]55#[derive(Debug)]
...@@ -75,13 +85,16 @@ pub enum Ast {...@@ -75,13 +85,16 @@ pub enum Ast {
75 name: String,85 name: String,
76 arguments: Vec<Argument>,86 arguments: Vec<Argument>,
77 return_type: Type,87 return_type: Type,
78 value: Vec<Ast>,88 block: Block
79 },89 },
80 FunctionCall {90 FunctionCall {
81 name: String,91 name: String,
82 arguments: Vec<Ast>,92 arguments: Vec<Ast>,
83 },93 },
94 Block(Block),
84 Number(String),95 Number(String),
96 Bool(bool),
97 String(String),
85 Identifier(String),98 Identifier(String),
86 Comment(String),99 Comment(String),
87 DocComment(String),100 DocComment(String),
compiler/src/tokenizer.rs+24
...@@ -15,12 +15,17 @@ pub enum Token {...@@ -15,12 +15,17 @@ pub enum Token {
15 // Literals15 // Literals
16 Identifier(String),16 Identifier(String),
17 Number(String),17 Number(String),
18 String(String),
18 // Comments19 // Comments
19 Comment(String),20 Comment(String),
20 DocComment(String),21 DocComment(String),
21 // Keywords22 // Keywords
23 True,
24 False,
22 Let,25 Let,
23 Var,26 Var,
27 If,
28 Else,
24 Return,29 Return,
25 Pub,30 Pub,
26 Function,31 Function,
...@@ -65,12 +70,31 @@ pub fn tokenize(content: String) -> Result<Vec<Token>> {...@@ -65,12 +70,31 @@ pub fn tokenize(content: String) -> Result<Vec<Token>> {
65 match current_token.as_str() {70 match current_token.as_str() {
66 "var" => tokens.push(Token::Var),71 "var" => tokens.push(Token::Var),
67 "let" => tokens.push(Token::Let),72 "let" => tokens.push(Token::Let),
73 "if" => tokens.push(Token::If),
74 "else" => tokens.push(Token::Else),
68 "pub" => tokens.push(Token::Pub),75 "pub" => tokens.push(Token::Pub),
69 "fn" => tokens.push(Token::Function),76 "fn" => tokens.push(Token::Function),
70 "return" => tokens.push(Token::Return),77 "return" => tokens.push(Token::Return),
78 "true" => tokens.push(Token::True),
79 "false" => tokens.push(Token::False),
71 _ => tokens.push(Token::Identifier(current_token)),80 _ => tokens.push(Token::Identifier(current_token)),
72 }81 }
73 }82 }
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 }
74 '0'..='9' => {98 '0'..='9' => {
75 let mut current_token = String::new();99 let mut current_token = String::new();
76 current_token.push(c);100 current_token.push(c);
compiler/src/walker.rs+22-2
...@@ -6,6 +6,8 @@ fn transpile_helper(tree: &Ast) -> Result<String> {...@@ -6,6 +6,8 @@ fn transpile_helper(tree: &Ast) -> Result<String> {
6 Ok(match tree {6 Ok(match tree {
7 Ast::Number(number) => format!("{}", number),7 Ast::Number(number) => format!("{}", number),
8 Ast::Identifier(name) => format!("{}", name),8 Ast::Identifier(name) => format!("{}", name),
9 Ast::Bool(value) => format!("{}", value),
10 Ast::String(value) => format!("\"{}\"", value),
9 Ast::Comment(comment) => format!("// {}\n", comment),11 Ast::Comment(comment) => format!("// {}\n", comment),
10 Ast::DocComment(comment) => format!("/** {} */\n", comment),12 Ast::DocComment(comment) => format!("/** {} */\n", comment),
11 Ast::Operation {13 Ast::Operation {
...@@ -40,7 +42,7 @@ fn transpile_helper(tree: &Ast) -> Result<String> {...@@ -40,7 +42,7 @@ fn transpile_helper(tree: &Ast) -> Result<String> {
40 name,42 name,
41 arguments,43 arguments,
42 return_type: _,44 return_type: _,
43 value,45 block
44 } => {46 } => {
45 let mut result = format!("function {}(", name);47 let mut result = format!("function {}(", name);
4648
...@@ -54,7 +56,11 @@ fn transpile_helper(tree: &Ast) -> Result<String> {...@@ -54,7 +56,11 @@ fn transpile_helper(tree: &Ast) -> Result<String> {
5456
55 result += ") {\n";57 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 }
58 result += transpile_helper(statement)?.as_str();64 result += transpile_helper(statement)?.as_str();
59 }65 }
6066
...@@ -78,6 +84,20 @@ fn transpile_helper(tree: &Ast) -> Result<String> {...@@ -78,6 +84,20 @@ fn transpile_helper(tree: &Ast) -> Result<String> {
7884
79 result += ")";85 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
81 result101 result
82 }102 }
83 })103 })
examples/basics/control.blight+4
...@@ -1 +1,5 @@...@@ -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 @@...@@ -1,5 +1,5 @@
1fn bingus(x: int, y: int) -> int {1fn bingus(x: int, y: int) -> int {
2 return x * y;2 x * y
3}3}
44
5let result: int = bingus(10, 25);5let result: int = bingus(10, 25);