authorgravatar for 11367844+lino-levan@users.noreply.github.comLino Le Van <11367844+lino-levan@users.noreply.github.com> 2024-01-18 19:07:38-08:00
committergravatar for 11367844+lino-levan@users.noreply.github.comLino Le Van <11367844+lino-levan@users.noreply.github.com> 2024-01-18 19:07:38-08:00
log2900f23394e35089aca94dbd1de195c7666365df
tree63fc7d53b2754c3f33a86f8813c086511d9bfa2a
parent8133856c0042befc85ff2725f34dfb71d50b1095

feat: add raw


21 files changed, 192 insertions(+), 189 deletions(-)

.github/logo.png created
Binary files /dev/null and b/.github/logo.png differ
README.md+2
...@@ -1,3 +1,5 @@...@@ -1,3 +1,5 @@
1![Blight Logo](/.github/logo.png)
2
1# Blight3# Blight
24
3Blight sure is a programming language.5Blight sure is a programming language.
crates/ast/src/lib.rs+1
...@@ -3,6 +3,7 @@ use miette::Result;...@@ -3,6 +3,7 @@ use miette::Result;
3mod error;3mod error;
4mod parse_block;4mod parse_block;
5mod parse_expression;5mod parse_expression;
6mod parse_function_call;
6mod parse_statement;7mod parse_statement;
7mod parse_type;8mod parse_type;
8mod types;9mod types;
crates/ast/src/parse_expression.rs+19-35
...@@ -4,6 +4,7 @@ use tokenizer::Token;...@@ -4,6 +4,7 @@ use tokenizer::Token;
44
5use super::error::AstError;5use super::error::AstError;
6use super::parse_block::parse_block;6use super::parse_block::parse_block;
7use super::parse_function_call::parse_function_call;
7use super::types::{Ast, Block, ParserContext};8use super::types::{Ast, Block, ParserContext};
89
9pub fn parse_expression(tokens: &mut ParserContext) -> Result<Ast> {10pub fn parse_expression(tokens: &mut ParserContext) -> Result<Ast> {
...@@ -11,6 +12,16 @@ pub fn parse_expression(tokens: &mut ParserContext) -> Result<Ast> {...@@ -11,6 +12,16 @@ pub fn parse_expression(tokens: &mut ParserContext) -> Result<Ast> {
11 Some(token) => match token {12 Some(token) => match token {
12 Token::Number(number) => Ast::Number(number),13 Token::Number(number) => Ast::Number(number),
13 Token::String(string) => Ast::String(string.clone()),14 Token::String(string) => Ast::String(string.clone()),
15 Token::BuiltIn(name) => {
16 match tokens.peek() {
17 Some(Token::OpenParanthesis) => {
18 // FRICK we consumed the open paranthesis
19 tokens.back();
20 parse_function_call(tokens)?
21 }
22 _ => Ast::BuiltIn(name.clone()),
23 }
24 }
14 Token::True => Ast::Bool(true),25 Token::True => Ast::Bool(true),
15 Token::False => Ast::Bool(false),26 Token::False => Ast::Bool(false),
16 Token::OpenBracket => {27 Token::OpenBracket => {
...@@ -57,43 +68,16 @@ pub fn parse_expression(tokens: &mut ParserContext) -> Result<Ast> {...@@ -57,43 +68,16 @@ pub fn parse_expression(tokens: &mut ParserContext) -> Result<Ast> {
57 else_value,68 else_value,
58 });69 });
59 }70 }
60 Token::Identifier(name) => match tokens.peek() {71 Token::Identifier(name) => {
61 Some(Token::OpenParanthesis) => {72 match tokens.peek() {
62 tokens.next();73 Some(Token::OpenParanthesis) => {
6374 // FRICK we consumed the open paranthesis
64 let mut arguments = Vec::new();75 tokens.back();
6576 parse_function_call(tokens)?
66 loop {
67 match tokens.peek() {
68 Some(Token::ClosedParanthesis) => {
69 tokens.next();
70 break;
71 }
72 _ => (),
73 }
74 arguments.push(parse_expression(tokens)?);
75
76 match tokens.peek() {
77 Some(Token::Comma) => {
78 tokens.next();
79 }
80 Some(Token::ClosedParanthesis) => (),
81 _ => {
82 return Err(AstError::new(
83 "Expected ) or , but found something else instead.",
84 )
85 .into())
86 }
87 }
88 }
89
90 Ast::FunctionCall {
91 name: name.clone(),
92 arguments,
93 }77 }
78 _ => Ast::Identifier(name.clone()),
94 }79 }
95 _ => Ast::Identifier(name.clone()),80 }
96 },
97 _ => {81 _ => {
98 println!("token: {:?}", token);82 println!("token: {:?}", token);
99 return Err(AstError::new("Expected expression, but did not get it").into());83 return Err(AstError::new("Expected expression, but did not get it").into());
crates/ast/src/parse_function_call.rs created+56
...@@ -0,0 +1,56 @@
1use miette::Result;
2
3use tokenizer::Token;
4
5use super::error::AstError;
6use super::parse_expression::parse_expression;
7use super::types::{Ast, ParserContext};
8
9/// Parses a function call AS AN EXPRESSION
10/// This does not consume the semicolon at the end of the function call
11/// if it is a statement.
12pub fn parse_function_call(tokens: &mut ParserContext) -> Result<Ast> {
13 let identifier = match tokens.next() {
14 Some(Token::Identifier(identifier)) => Ast::Identifier(identifier),
15 Some(Token::BuiltIn(identifier)) => Ast::BuiltIn(identifier),
16 _ => return Err(AstError::new("Expected identifier").into()),
17 };
18
19 match tokens.peek() {
20 Some(Token::OpenParanthesis) => {
21 tokens.next();
22
23 let mut arguments = Vec::new();
24
25 loop {
26 match tokens.peek() {
27 Some(Token::ClosedParanthesis) => {
28 tokens.next();
29 break;
30 }
31 _ => (),
32 }
33 arguments.push(parse_expression(tokens)?);
34
35 match tokens.peek() {
36 Some(Token::Comma) => {
37 tokens.next();
38 }
39 Some(Token::ClosedParanthesis) => (),
40 _ => {
41 return Err(AstError::new(
42 "Expected ) or , but found something else instead.",
43 )
44 .into())
45 }
46 }
47 }
48
49 Ok(Ast::FunctionCall {
50 name: Box::new(identifier),
51 arguments,
52 })
53 }
54 _ => Err(AstError::new("Unexpected identifier").into()),
55 }
56}
crates/ast/src/parse_statement.rs+23-36
...@@ -5,6 +5,7 @@ use tokenizer::Token;...@@ -5,6 +5,7 @@ use tokenizer::Token;
5use super::error::AstError;5use super::error::AstError;
6use super::parse_block::parse_block;6use super::parse_block::parse_block;
7use super::parse_expression::parse_expression;7use super::parse_expression::parse_expression;
8use super::parse_function_call::parse_function_call;
8use super::parse_type::parse_type;9use super::parse_type::parse_type;
9use super::types::{Argument, Ast, Block, ParserContext};10use super::types::{Argument, Ast, Block, ParserContext};
1011
...@@ -12,6 +13,16 @@ use super::types::{Argument, Ast, Block, ParserContext};...@@ -12,6 +13,16 @@ use super::types::{Argument, Ast, Block, ParserContext};
12pub fn parse_statement(tokens: &mut ParserContext) -> Result<Ast> {13pub fn parse_statement(tokens: &mut ParserContext) -> Result<Ast> {
13 let token = tokens.next().unwrap();14 let token = tokens.next().unwrap();
14 match token {15 match token {
16 Token::BuiltIn(name) => {
17 match tokens.peek() {
18 Some(Token::OpenParanthesis) => {
19 // Okay, so we messed up. We shouldn't have consumed that token.
20 tokens.back();
21 parse_function_call(tokens)
22 }
23 _ => Ok(Ast::BuiltIn(name)),
24 }
25 }
15 Token::OpenBracket => {26 Token::OpenBracket => {
16 // FRICK, we have to backtrack27 // FRICK, we have to backtrack
17 tokens.back();28 tokens.back();
...@@ -44,7 +55,7 @@ pub fn parse_statement(tokens: &mut ParserContext) -> Result<Ast> {...@@ -44,7 +55,7 @@ pub fn parse_statement(tokens: &mut ParserContext) -> Result<Ast> {
44 Some(Token::Semicolon) => (),55 Some(Token::Semicolon) => (),
45 _ => {56 _ => {
46 return Err(57 return Err(
47 AstError::new("Expected semicolon after variable declaration").into(),58 AstError::new("Expected semicolon after constant declaration").into(),
48 )59 )
49 }60 }
50 };61 };
...@@ -213,45 +224,21 @@ pub fn parse_statement(tokens: &mut ParserContext) -> Result<Ast> {...@@ -213,45 +224,21 @@ pub fn parse_statement(tokens: &mut ParserContext) -> Result<Ast> {
213 else_value,224 else_value,
214 });225 });
215 }226 }
216 Token::Identifier(name) => match tokens.peek() {227 Token::Identifier(_) => match tokens.peek() {
217 Some(Token::OpenParanthesis) => {228 Some(Token::OpenParanthesis) => {
218 tokens.next();229 // We need to give the identifier back to the parser
219230 tokens.back();
220 let mut arguments = Vec::new();231 let result = parse_function_call(tokens);
221
222 loop {
223 match tokens.peek() {
224 Some(Token::ClosedParanthesis) => {
225 tokens.next();
226 break;
227 }
228 _ => (),
229 }
230 arguments.push(parse_expression(tokens)?);
231
232 match tokens.peek() {
233 Some(Token::Comma) => {
234 tokens.next();
235 }
236 Some(Token::ClosedParanthesis) => (),
237 _ => {
238 return Err(AstError::new(
239 "Expected ) or , but found something else instead.",
240 )
241 .into())
242 }
243 }
244 }
245
246 match tokens.next() {232 match tokens.next() {
247 Some(Token::Semicolon) => (),233 Some(Token::Semicolon) => (),
248 _ => return Err(AstError::new("Expected semicolon after function call").into()),234 _ => {
235 return Err(AstError::new(
236 "Expected semicolon after function call statement",
237 )
238 .into())
239 }
249 };240 };
250241 result
251 Ok(Ast::FunctionCall {
252 name: name.clone(),
253 arguments,
254 })
255 }242 }
256 _ => Err(AstError::new("Unexpected identifier").into()),243 _ => Err(AstError::new("Unexpected identifier").into()),
257 },244 },
crates/ast/src/parse_type.rs+1
...@@ -13,6 +13,7 @@ pub fn parse_type(tokens: &mut ParserContext) -> Result<Type> {...@@ -13,6 +13,7 @@ pub fn parse_type(tokens: &mut ParserContext) -> Result<Type> {
13 "bigint" => Ok(Type::Bigint),13 "bigint" => Ok(Type::Bigint),
14 "bool" => Ok(Type::Bool),14 "bool" => Ok(Type::Bool),
15 "string" => Ok(Type::String),15 "string" => Ok(Type::String),
16 "any" => Ok(Type::Any),
16 _ => return Err(AstError::new("Expected type").into()),17 _ => return Err(AstError::new("Expected type").into()),
17 },18 },
18 _ => return Err(AstError::new("Expected type").into()),19 _ => return Err(AstError::new("Expected type").into()),
crates/ast/src/types.rs+8-5
...@@ -41,28 +41,29 @@ impl ParserContext {...@@ -41,28 +41,29 @@ impl ParserContext {
41 }41 }
42}42}
4343
44#[derive(Debug)]44#[derive(Debug, Clone)]
45pub enum Type {45pub enum Type {
46 Int,46 Int,
47 Float,47 Float,
48 Bigint,48 Bigint,
49 Bool,49 Bool,
50 String,50 String,
51 Any,
51}52}
5253
53#[derive(Debug)]54#[derive(Debug, Clone)]
54pub struct Block {55pub struct Block {
55 pub value: Vec<Ast>,56 pub value: Vec<Ast>,
56 pub implicit_return: bool,57 pub implicit_return: bool,
57}58}
5859
59#[derive(Debug)]60#[derive(Debug, Clone)]
60pub struct Argument {61pub struct Argument {
61 pub name: String,62 pub name: String,
62 pub return_type: Type,63 pub return_type: Type,
63}64}
6465
65#[derive(Debug)]66#[derive(Debug, Clone)]
66pub enum Ast {67pub enum Ast {
67 ConstantDeclaration {68 ConstantDeclaration {
68 name: String,69 name: String,
...@@ -86,7 +87,8 @@ pub enum Ast {...@@ -86,7 +87,8 @@ pub enum Ast {
86 block: Block,87 block: Block,
87 },88 },
88 FunctionCall {89 FunctionCall {
89 name: String,90 /// Identifier or BuiltIn
91 name: Box<Ast>,
90 arguments: Vec<Ast>,92 arguments: Vec<Ast>,
91 },93 },
92 If {94 If {
...@@ -101,6 +103,7 @@ pub enum Ast {...@@ -101,6 +103,7 @@ pub enum Ast {
101 Bool(bool),103 Bool(bool),
102 String(String),104 String(String),
103 Identifier(String),105 Identifier(String),
106 BuiltIn(String),
104 Comment(String),107 Comment(String),
105 DocComment(String),108 DocComment(String),
106}109}
crates/js_ast/src/lib.rs+46-104
...@@ -109,10 +109,27 @@ fn get_expression_handle(ast: &Ast, ctx: &mut TranslateContext) -> JsExpression...@@ -109,10 +109,27 @@ fn get_expression_handle(ast: &Ast, ctx: &mut TranslateContext) -> JsExpression
109 for argument in arguments {109 for argument in arguments {
110 handles.push(get_expression_handle(argument, ctx));110 handles.push(get_expression_handle(argument, ctx));
111 }111 }
112 ctx.push_internal_variable(JsExpression::FunctionCall {112 match *name.clone() {
113 name: ctx.get_identifier(name.clone()),113 Ast::Identifier(name) => ctx.push_internal_variable(JsExpression::FunctionCall {
114 arguments: handles,114 name: Box::new(JsExpression::Identifier(ctx.get_identifier(name.clone()))),
115 })115 arguments: handles,
116 }),
117 Ast::BuiltIn(name) => match name.as_str() {
118 "@raw" => {
119 if handles.len() != 1 {
120 panic!("@raw expects exactly one argument");
121 }
122 match handles.get(0).unwrap() {
123 JsExpression::String(value) => {
124 return JsExpression::Raw(value.clone());
125 }
126 _ => panic!("@raw expects a string argument"),
127 }
128 }
129 _ => panic!("Unknown built-in function {}", name),
130 },
131 _ => panic!("Function name must be an identifier"),
132 }
116 }133 }
117 Ast::Operation {134 Ast::Operation {
118 operator,135 operator,
...@@ -286,13 +303,32 @@ fn translate_statement(ast: &Ast, ctx: &mut TranslateContext) {...@@ -286,13 +303,32 @@ fn translate_statement(ast: &Ast, ctx: &mut TranslateContext) {
286 for argument in arguments {303 for argument in arguments {
287 handles.push(get_expression_handle(argument, ctx));304 handles.push(get_expression_handle(argument, ctx));
288 }305 }
289 ctx.push(JsStatement::Expression(JsExpression::FunctionCall {306 match *name.clone() {
290 name: match name.as_str() {307 Ast::Identifier(name) => {
291 "print" => "console.log".to_string(),308 ctx.push(JsStatement::Expression(JsExpression::FunctionCall {
292 _ => name.clone(),309 name: Box::new(JsExpression::Identifier(ctx.get_identifier(name.clone()))),
310 arguments: handles,
311 }));
312 }
313 Ast::BuiltIn(name) => match name.as_str() {
314 "@raw" => {
315 if handles.len() != 1 {
316 panic!("@raw expects exactly one argument");
317 }
318 match handles.get(0).unwrap() {
319 JsExpression::String(value) => {
320 ctx.push(JsStatement::Expression(JsExpression::FunctionCall {
321 name: Box::new(JsExpression::Raw(value.clone())),
322 arguments: handles,
323 }));
324 }
325 _ => panic!("@raw expects a string argument"),
326 }
327 }
328 _ => panic!("Unknown built-in function {}", name),
293 },329 },
294 arguments: handles,330 _ => panic!("Function name must be an identifier"),
295 }));331 }
296 }332 }
297 Ast::Comment(_) | Ast::DocComment(_) => {}333 Ast::Comment(_) | Ast::DocComment(_) => {}
298 _ => {334 _ => {
...@@ -310,97 +346,3 @@ pub fn translate(_ast: Vec<Ast>) -> Result<Vec<JsStatement>> {...@@ -310,97 +346,3 @@ pub fn translate(_ast: Vec<Ast>) -> Result<Vec<JsStatement>> {
310346
311 Ok(ctx.pop_context())347 Ok(ctx.pop_context())
312}348}
313
314#[cfg(test)]
315mod tests {
316 use crate::translate;
317 use crate::{JsExpression, JsStatement};
318 use ast::{Ast, Type};
319 use util::Operator;
320
321 #[test]
322 fn test_translate() {
323 let ast = Ast::ConstantDeclaration {
324 name: "hi".to_string(),
325 return_type: Type::Int,
326 value: Box::new(Ast::Operation {
327 operator: Operator::Add,
328 left: Box::new(Ast::Operation {
329 operator: Operator::Add,
330 left: Box::new(Ast::Number(1.0)),
331 right: Box::new(Ast::Operation {
332 operator: Operator::Add,
333 left: Box::new(Ast::Number(2.0)),
334 right: Box::new(Ast::Number(3.0)),
335 }),
336 }),
337 right: Box::new(Ast::Operation {
338 operator: Operator::Add,
339 left: Box::new(Ast::Number(4.0)),
340 right: Box::new(Ast::Number(5.0)),
341 }),
342 }),
343 };
344 assert_eq!(
345 translate(vec![ast]).unwrap(),
346 vec![
347 JsStatement::ConstantDeclaration {
348 name: "$0".to_string(),
349 value: JsExpression::Number(1.0)
350 },
351 JsStatement::ConstantDeclaration {
352 name: "$1".to_string(),
353 value: JsExpression::Number(2.0)
354 },
355 JsStatement::ConstantDeclaration {
356 name: "$2".to_string(),
357 value: JsExpression::Number(3.0)
358 },
359 JsStatement::ConstantDeclaration {
360 name: "$3".to_string(),
361 value: JsExpression::Operation {
362 operator: Operator::Add,
363 left: Box::new(JsExpression::Identifier("$1".to_string())),
364 right: Box::new(JsExpression::Identifier("$2".to_string()))
365 }
366 },
367 JsStatement::ConstantDeclaration {
368 name: "$4".to_string(),
369 value: JsExpression::Operation {
370 operator: Operator::Add,
371 left: Box::new(JsExpression::Identifier("$0".to_string())),
372 right: Box::new(JsExpression::Identifier("$3".to_string()))
373 }
374 },
375 JsStatement::ConstantDeclaration {
376 name: "$5".to_string(),
377 value: JsExpression::Number(4.0)
378 },
379 JsStatement::ConstantDeclaration {
380 name: "$6".to_string(),
381 value: JsExpression::Number(5.0)
382 },
383 JsStatement::ConstantDeclaration {
384 name: "$7".to_string(),
385 value: JsExpression::Operation {
386 operator: Operator::Add,
387 left: Box::new(JsExpression::Identifier("$5".to_string())),
388 right: Box::new(JsExpression::Identifier("$6".to_string()))
389 }
390 },
391 JsStatement::ConstantDeclaration {
392 name: "$8".to_string(),
393 value: JsExpression::Operation {
394 operator: Operator::Add,
395 left: Box::new(JsExpression::Identifier("$4".to_string())),
396 right: Box::new(JsExpression::Identifier("$7".to_string()))
397 }
398 },
399 JsStatement::ConstantDeclaration {
400 name: "hi".to_string(),
401 value: JsExpression::Identifier("$8".to_string())
402 }
403 ]
404 )
405 }
406}
crates/js_ast/src/types.rs+2-1
...@@ -10,6 +10,7 @@ pub enum JsExpression {...@@ -10,6 +10,7 @@ pub enum JsExpression {
10 String(String),10 String(String),
11 Bool(bool),11 Bool(bool),
12 Identifier(String),12 Identifier(String),
13 Raw(String),
13 Array(Vec<JsExpression>),14 Array(Vec<JsExpression>),
14 Object(HashMap<String, JsExpression>),15 Object(HashMap<String, JsExpression>),
15 Operation {16 Operation {
...@@ -22,7 +23,7 @@ pub enum JsExpression {...@@ -22,7 +23,7 @@ pub enum JsExpression {
22 value: Vec<JsStatement>,23 value: Vec<JsStatement>,
23 },24 },
24 FunctionCall {25 FunctionCall {
25 name: String,26 name: Box<JsExpression>,
26 arguments: Vec<JsExpression>,27 arguments: Vec<JsExpression>,
27 },28 },
28}29}
crates/js_printer/src/print_expression.rs+9-4
...@@ -4,6 +4,7 @@ use crate::print_statement::print_statement;...@@ -4,6 +4,7 @@ use crate::print_statement::print_statement;
44
5pub fn print_expression(statement: &JsExpression) -> String {5pub fn print_expression(statement: &JsExpression) -> String {
6 match statement {6 match statement {
7 JsExpression::Raw(value) => format!("{}", value),
7 JsExpression::Number(value) => format!("{}", value),8 JsExpression::Number(value) => format!("{}", value),
8 JsExpression::BigInt(value) => format!("{}n", value),9 JsExpression::BigInt(value) => format!("{}n", value),
9 JsExpression::String(value) => {10 JsExpression::String(value) => {
...@@ -61,7 +62,11 @@ pub fn print_expression(statement: &JsExpression) -> String {...@@ -61,7 +62,11 @@ pub fn print_expression(statement: &JsExpression) -> String {
61 ),62 ),
62 JsExpression::FunctionCall { name, arguments } => format!(63 JsExpression::FunctionCall { name, arguments } => format!(
63 "{}({})",64 "{}({})",
64 name,65 match *name.clone() {
66 JsExpression::Identifier(value) => value.clone(),
67 JsExpression::Raw(value) => value.clone(),
68 _ => panic!("Function call name must be an identifier"),
69 },
65 arguments70 arguments
66 .iter()71 .iter()
67 .map(|x| print_expression(x))72 .map(|x| print_expression(x))
...@@ -238,21 +243,21 @@ mod tests {...@@ -238,21 +243,21 @@ mod tests {
238 fn function_call() {243 fn function_call() {
239 assert_eq!(244 assert_eq!(
240 print_expression(&JsExpression::FunctionCall {245 print_expression(&JsExpression::FunctionCall {
241 name: "hello".to_string(),246 name: Box::new(JsExpression::Identifier("hello".to_string())),
242 arguments: vec![],247 arguments: vec![],
243 }),248 }),
244 "hello()"249 "hello()"
245 );250 );
246 assert_eq!(251 assert_eq!(
247 print_expression(&JsExpression::FunctionCall {252 print_expression(&JsExpression::FunctionCall {
248 name: "hello".to_string(),253 name: Box::new(JsExpression::Identifier("hello".to_string())),
249 arguments: vec![JsExpression::Number(1.0)],254 arguments: vec![JsExpression::Number(1.0)],
250 }),255 }),
251 "hello(1)"256 "hello(1)"
252 );257 );
253 assert_eq!(258 assert_eq!(
254 print_expression(&JsExpression::FunctionCall {259 print_expression(&JsExpression::FunctionCall {
255 name: "hello".to_string(),260 name: Box::new(JsExpression::Identifier("hello".to_string())),
256 arguments: vec![JsExpression::Number(1.0), JsExpression::Number(2.0)],261 arguments: vec![JsExpression::Number(1.0), JsExpression::Number(2.0)],
257 }),262 }),
258 "hello(1,2)"263 "hello(1,2)"
crates/tokenizer/src/lib.rs+9-2
...@@ -16,6 +16,7 @@ pub enum Token {...@@ -16,6 +16,7 @@ pub enum Token {
16 Identifier(String),16 Identifier(String),
17 Number(f64),17 Number(f64),
18 String(String),18 String(String),
19 BuiltIn(String),
19 // Comments20 // Comments
20 Comment(String),21 Comment(String),
21 DocComment(String),22 DocComment(String),
...@@ -49,7 +50,7 @@ pub fn tokenize(content: String) -> Result<Vec<Token>> {...@@ -49,7 +50,7 @@ pub fn tokenize(content: String) -> Result<Vec<Token>> {
49 loop {50 loop {
50 match chars.next() {51 match chars.next() {
51 Some((_, c)) => match c {52 Some((_, c)) => match c {
52 'a'..='z' | 'A'..='Z' | '_' => {53 'a'..='z' | 'A'..='Z' | '_' | '@' => {
53 let mut current_token = String::new();54 let mut current_token = String::new();
54 current_token.push(c);55 current_token.push(c);
55 loop {56 loop {
...@@ -77,7 +78,13 @@ pub fn tokenize(content: String) -> Result<Vec<Token>> {...@@ -77,7 +78,13 @@ pub fn tokenize(content: String) -> Result<Vec<Token>> {
77 "return" => tokens.push(Token::Return),78 "return" => tokens.push(Token::Return),
78 "true" => tokens.push(Token::True),79 "true" => tokens.push(Token::True),
79 "false" => tokens.push(Token::False),80 "false" => tokens.push(Token::False),
80 _ => tokens.push(Token::Identifier(current_token)),81 _ => {
82 if current_token.starts_with('@') {
83 tokens.push(Token::BuiltIn(current_token));
84 } else {
85 tokens.push(Token::Identifier(current_token))
86 }
87 }
81 }88 }
82 }89 }
83 '"' => {90 '"' => {
examples/basics/control.blight+2
...@@ -1,3 +1,5 @@...@@ -1,3 +1,5 @@
1let print: any = @raw("console.log");
2
1let x: bool = true;3let x: bool = true;
24
3if x {5if x {
examples/basics/expressions.blight+1
...@@ -7,4 +7,5 @@ let x: int = 5 + {...@@ -7,4 +7,5 @@ let x: int = 5 + {
7 y7 y
8};8};
99
10let print: any = @raw("console.log");
10print(x); // 1011print(x); // 10
examples/basics/fib.blight+1
...@@ -8,4 +8,5 @@ pub fn fib(n: int) -> int {...@@ -8,4 +8,5 @@ pub fn fib(n: int) -> int {
8 }8 }
9}9}
1010
11let print: any = @raw("console.log");
11print(fib(10));12print(fib(10));
examples/basics/functions.blight+2-1
...@@ -4,4 +4,5 @@ fn bingus(x: int, y: int) -> int {...@@ -4,4 +4,5 @@ fn bingus(x: int, y: int) -> int {
44
5let result: int = bingus(10, 25);5let result: int = bingus(10, 25);
66
7print(result); // built-in function7let print: any = @raw("console.log");
8print(result);
examples/basics/operations.blight+3
...@@ -1 +1,4 @@...@@ -1 +1,4 @@
1let a: int = 10 - 2 / 4 * 15;1let a: int = 10 - 2 / 4 * 15;
2
3let print: any = @raw("console.log");
4print(a);
examples/basics/shadowing.blight+2
...@@ -1,3 +1,5 @@...@@ -1,3 +1,5 @@
1let print: any = @raw("console.log");
2
1let x: int = 0;3let x: int = 0;
2let x: int = 1;4let x: int = 1;
3print(x); // 15print(x); // 1
examples/basics/variables.blight+3
...@@ -5,3 +5,6 @@ var z: bigint = 0;...@@ -5,3 +5,6 @@ var z: bigint = 0;
5let a: int = 0;5let a: int = 0;
6let b: float = 0;6let b: float = 0;
7let c: bigint = 0;7let c: bigint = 0;
8
9let print: any = @raw("console.log");
10print(x);
examples/basics/weird.blight+1
...@@ -9,5 +9,6 @@ fn bingus(y: bool) -> int {...@@ -9,5 +9,6 @@ fn bingus(y: bool) -> int {
9 x9 x
10}10}
1111
12let print: any = @raw("console.log");
12print(bingus(true));13print(bingus(true));
13print(bingus(false));14print(bingus(false));
examples/interop/blight_in_js/main.js+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1import { add, TOP_LEVEL } from "./add.js";1import { add, TOP_LEVEL } from "./add.js";
22
3console.log(add(1, 2));3console.log(add(1, 2));
4console.log(TOP_LEVEL)4console.log(TOP_LEVEL);