diff --git a/.gitignore b/.gitignore index eb5a316cbd195d26e3f768c7dd8e1b47299e17f8..4143657114f43375f7bb260327bd203355dcd140 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ target +*.js diff --git a/Cargo.lock b/Cargo.lock index 426f40ae047164d1a7ae0edd8328a6bcc3bc0da0..8317b65192cbb35945e6d398cc412aea7bcee045 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -126,6 +126,17 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "checker" +version = "0.1.0" +dependencies = [ + "ast", + "miette", + "num", + "thiserror", + "util", +] + [[package]] name = "clap" version = "4.4.14" @@ -171,6 +182,7 @@ name = "cli" version = "0.1.0" dependencies = [ "ast", + "checker", "clap", "js_ast", "js_printer", diff --git a/crates/ast/src/error.rs b/crates/ast/src/error.rs index f698cb95d6c28ff61e24bab5161acbd133992c78..c04c6362d317fb2623d187a22a7a78dee72982ff 100644 --- a/crates/ast/src/error.rs +++ b/crates/ast/src/error.rs @@ -14,4 +14,8 @@ impl AstError { error: String::from(error), } } + + pub fn from_string(error: String) -> AstError { + AstError { error } + } } diff --git a/crates/ast/src/lib.rs b/crates/ast/src/lib.rs index c4841db4e84a9184793e9563f94d5e15b3dbaa66..3810f82f7e30940a92838648832212aeddf5443c 100644 --- a/crates/ast/src/lib.rs +++ b/crates/ast/src/lib.rs @@ -13,9 +13,9 @@ use tokenizer::Token; use parse_statement::parse_statement; use types::ParserContext; -pub use types::{Ast, Block, Type}; +pub use types::{Ast, Block, Module, Type}; -pub fn parse(tokens: Vec) -> Result> { +pub fn parse(tokens: Vec) -> Result { let mut ctx = ParserContext::new(tokens); let mut ast: Vec = Vec::new(); @@ -23,5 +23,5 @@ pub fn parse(tokens: Vec) -> Result> { ast.push(parse_statement(&mut ctx)?); } - Ok(ast) + Ok(Module { value: ast }) } diff --git a/crates/ast/src/parse_statement.rs b/crates/ast/src/parse_statement.rs index 343aceff9eea0e9fc29c57e25fab2387e39f8b32..1286c41fd08bdcc6267f855fa7b1a40df9056004 100644 --- a/crates/ast/src/parse_statement.rs +++ b/crates/ast/src/parse_statement.rs @@ -2,6 +2,8 @@ use miette::Result; use tokenizer::Token; +use crate::Type; + use super::error::AstError; use super::parse_block::parse_block; use super::parse_expression::parse_expression; @@ -38,14 +40,22 @@ pub fn parse_statement(tokens: &mut ParserContext) -> Result { return Ok(Ast::Public(Box::new(inner))); } - Token::Let => { + Token::Var | Token::Let => { + let is_constant = match token { + Token::Var => false, + Token::Let => true, + _ => unreachable!(), + }; let name = match tokens.next() { Some(Token::Identifier(name)) => name, _ => return Err(AstError::new("Expected identifier after var").into()), }; - let return_type = match tokens.next() { - Some(Token::Colon) => parse_type(tokens)?, - _ => return Err(AstError::new("Expected colon after identifier").into()), + let return_type = match tokens.peek() { + Some(Token::Colon) => { + tokens.next(); + parse_type(tokens)? + } + _ => Type::Infer, }; let value = match tokens.next() { Some(Token::Equals) => parse_expression(tokens)?, @@ -59,37 +69,11 @@ pub fn parse_statement(tokens: &mut ParserContext) -> Result { ) } }; - Ok(Ast::ConstantDeclaration { + Ok(Ast::Declaration { name: name.clone(), - return_type, - value: Box::new(value), - }) - } - Token::Var => { - let name = match tokens.next() { - Some(Token::Identifier(name)) => name, - _ => return Err(AstError::new("Expected identifier after var").into()), - }; - let return_type = match tokens.next() { - Some(Token::Colon) => parse_type(tokens)?, - _ => return Err(AstError::new("Expected colon after identifier").into()), - }; - let value = match tokens.next() { - Some(Token::Equals) => parse_expression(tokens)?, - _ => return Err(AstError::new("Expected equals after identifier").into()), - }; - match tokens.next() { - Some(Token::Semicolon) => (), - _ => { - return Err( - AstError::new("Expected semicolon after variable declaration").into(), - ) - } - }; - Ok(Ast::VariableDeclaration { - name: name.clone(), - return_type, + decl_type: return_type, value: Box::new(value), + is_constant, }) } Token::Return => { diff --git a/crates/ast/src/parse_type.rs b/crates/ast/src/parse_type.rs index 6837edec59b4d8f649ccc28c65f33362ef948c49..e481d0d283d7ad230ed89190f60b859134dfce4e 100644 --- a/crates/ast/src/parse_type.rs +++ b/crates/ast/src/parse_type.rs @@ -10,12 +10,19 @@ pub fn parse_type(tokens: &mut ParserContext) -> Result { Some(Token::Identifier(typ)) => match typ.as_str() { "int" => Ok(Type::Int), "float" => Ok(Type::Float), - "bigint" => Ok(Type::Bigint), + "bigint" => Ok(Type::BigInt), "bool" => Ok(Type::Bool), "string" => Ok(Type::String), - "any" => Ok(Type::Any), - _ => return Err(AstError::new("Expected type").into()), + _ => { + return Err( + AstError::from_string(format!( + "Invalid type '{}' (TODO: add custom type support)", + typ + ) + ).into()) + } }, - _ => return Err(AstError::new("Expected type").into()), + Some(unexpected) => return Err(AstError::from_string(format!("Expected type, got {}", unexpected)).into()), + None => return Err(AstError::from_string("Expected type, got EOF".to_string()).into()), } } diff --git a/crates/ast/src/types.rs b/crates/ast/src/types.rs index 3500088aa85499be1b8eb25c25ed7749ff58c598..61a84e57cd474bd406185292dfb87fa0cfeed8b3 100644 --- a/crates/ast/src/types.rs +++ b/crates/ast/src/types.rs @@ -41,14 +41,62 @@ impl ParserContext { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub enum Type { + /// Variables without an explicit type are assigned this until + /// the type inferencer figures out what this is. There is not a + /// keyword for this. + Infer, + /// The type assigned to numeric literals. This allows integer literals + /// to coerce to integer or float depending on the context, but prevents + /// implicit casting of runtime values. + NumberLiteral(f64), + /// Return value of `@raw`. All type checks are disabled. + Any, + /// noreturn is the type of 'return', aka a value that never exists + NoReturn, + /// 32 signed integer Int, + /// 64 signed JS float Float, - Bigint, + /// Boolean Bool, + /// JS BigInt + BigInt, + /// JS String String, - Any, + /// A union of multiple possible types. Might be removed + Union(Vec), +} + +impl std::fmt::Display for Type { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Type::Infer => write!(f, "infered type"), + Type::Any => write!(f, "opaque js value"), + Type::NumberLiteral(_) => write!(f, "numeric literal"), + Type::Int => write!(f, "int"), + Type::Float => write!(f, "float"), + Type::BigInt => write!(f, "bigint"), + Type::Bool => write!(f, "bool"), + Type::String => write!(f, "string"), + Type::NoReturn => write!(f, "noreturn"), + Type::Union(of) => { + for (i, t) in of.iter().enumerate() { + if i != 0 { + write!(f, " | ")?; + } + write!(f, "{}", t)?; + } + Ok(()) + } + } + } +} + +#[derive(Debug, Clone)] +pub struct Module { + pub value: Vec, } #[derive(Debug, Clone)] @@ -65,15 +113,11 @@ pub struct Argument { #[derive(Debug, Clone)] pub enum Ast { - ConstantDeclaration { + Declaration { name: String, - return_type: Type, - value: Box, - }, - VariableDeclaration { - name: String, - return_type: Type, + decl_type: Type, value: Box, + is_constant: bool, }, Operation { operator: Operator, diff --git a/crates/checker/Cargo.toml b/crates/checker/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..9911221e439591b90a010b7a36b71770a76c2305 --- /dev/null +++ b/crates/checker/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "checker" +version = "0.1.0" +edition = "2021" + +[lib] + +[dependencies] +miette.workspace = true +thiserror.workspace = true +num.workspace = true + +ast = { path = "../ast" } +util = { path = "../util" } diff --git a/crates/checker/src/lib.rs b/crates/checker/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..7f68543e0b5f8f27ec36090523bf10227dd0770a --- /dev/null +++ b/crates/checker/src/lib.rs @@ -0,0 +1,203 @@ +use ast::{Ast, Module, Type}; +use miette::Result; + +use miette::Diagnostic; +use thiserror::Error; + +#[derive(Error, Diagnostic, Debug)] +#[error("TypeError")] +pub struct TypeError { + #[help] + error: String, +} + +impl TypeError { + pub fn new(error: String) -> Self { + Self { error } + } +} + +pub fn check_module(block: &Module) -> Result<()> { + for statement in &block.value { + check_expression(statement)?; + } + + Ok(()) +} + +pub fn resolve_type(expr: &Ast) -> Result { + match expr { + Ast::Number(value) => Ok(Type::NumberLiteral(value.clone())), + Ast::Declaration { + name, + decl_type, + value, + is_constant, + } => Ok(Type::NoReturn), + Ast::Operation { + operator, + left, + right, + } => merge_types(resolve_type(left)?, resolve_type(right)?), + Ast::Function { + name, + arguments, + return_type, + block, + } => todo!(), + Ast::FunctionCall { name, arguments } => todo!(), + Ast::If { + condition, + value, + else_value, + } => todo!(), + Ast::Return(_) => Ok(Type::NoReturn), + Ast::Public(_) => todo!(), // TODO: remove Public + Ast::Block(_) => todo!(), + Ast::Bool(_) => Ok(Type::Bool), + Ast::String(_) => Ok(Type::String), + Ast::Identifier(_) => todo!(), + Ast::BuiltIn(_) => todo!(), + + Ast::Comment(_) => unreachable!(), + Ast::DocComment(_) => unreachable!(), + } +} + +pub fn merge_types(a: Type, b: Type) -> Result { + match a { + Type::Infer => return Ok(b), + Type::Any => return Ok(Type::Any), + _ => {} + } + + match b { + Type::Infer => return Ok(a), + Type::Any => return Ok(Type::Any), + _ => {} + } + + if a == b { + return Ok(a); + } + + Err(TypeError::new(format!("Cannot merge {} and {}", a, b)).into()) +} + +pub fn coerce_type(target: Type, source: Type) -> Result { + match source { + Type::Any => return Ok(target), + _ => {} + } + match target { + Type::Infer => Ok(source), + Type::Any => Ok(Type::Any), + + Type::NumberLiteral(_) => unreachable!(), + + Type::Int => match source { + Type::Int => Ok(Type::Int), + Type::Float => Ok(Type::Int), + Type::NumberLiteral(value) => { + if value.fract() != 0.0 { + Err( + TypeError::new(format!("Numeric Literal '{}' is not an integer", value)) + .into(), + ) + } else if value > i32::MAX.into() || value < i32::MIN.into() { + Err(TypeError::new(format!( + "Numeric Literal '{}' is out of range for an integer ({}..{})", + value, + i32::MIN, + i32::MAX + )) + .into()) + } else { + Ok(Type::Int) + } + } + t => Err(TypeError::new(format!("Cannot coerce {} to int", t)).into()), + }, + + Type::BigInt => match source { + Type::Int => Ok(Type::Int), + Type::Float => Ok(Type::Int), + Type::NumberLiteral(value) => { + if value.fract() != 0.0 { + Err( + TypeError::new(format!("Numeric Literal '{}' is not an integer", value)) + .into(), + ) + } else { + Ok(Type::BigInt) + } + } + t => Err(TypeError::new(format!("Cannot coerce {} to int", t)).into()), + }, + + Type::Float => match source { + Type::Int => Ok(Type::Float), + Type::Float => Ok(Type::Float), + Type::NumberLiteral(value) => { + if value.fract() == 0.0 && value <= f64::MAX.into() && value >= f64::MIN.into() { + Ok(Type::Float) + } else { + Err(TypeError::new(format!("Numeric Literal")).into()) + } + } + _ => Err(TypeError::new(format!("Cannot coerce int to float")).into()), + }, + + other => { + if other == source { + Ok(other) + } else { + Err(TypeError::new(format!("Cannot coerce {} to {}", source, other)).into()) + } + } + } +} + +pub fn check_expression(expr: &Ast) -> Result<()> { + match expr { + Ast::Declaration { + name, + decl_type: return_type, + value, + is_constant, + } => { + check_expression(value)?; + coerce_type(return_type.clone(), resolve_type(value)?)?; + } + _ => {} + // Ast::Operation { + // operator, + // left, + // right, + // } => Ok(()), + // Ast::Function { + // name, + // arguments, + // return_type, + // block, + // } => Ok(()), + // Ast::FunctionCall { name, arguments } => Ok(()), + // Ast::If { + // condition, + // value, + // else_value, + // } => Ok(()), + // Ast::Return(_) => Ok(()), + // Ast::Public(_) => Ok(()), + // Ast::Block(_) => Ok(()), + // Ast::Number(_) => Ok(()), + // Ast::Bool(_) => Ok(()), + // Ast::String(_) => Ok(()), + // Ast::Identifier(_) => Ok(()), + // Ast::BuiltIn(_) => Ok(()), + // Ast::Comment(_) => Ok(()), + // Ast::DocComment(_) => Ok(()), + } + + Ok(()) +} diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 0f6618aef8ab0f73dfad007939f2c13f827f0fa5..a0e6f101de7d10297488257b9f58ddb06354076d 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -16,3 +16,4 @@ tokenizer = { path = "../tokenizer" } ast = { path = "../ast" } js_ast = { path = "../js_ast" } js_printer = { path = "../js_printer" } +checker = { path = "../checker" } diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index e04af712afecd134f30a2d7e1afdf3a700673eba..254bad1c38f34c5af9d8a13b3c5e1b3482e93cd8 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -1,5 +1,6 @@ -use std::path::PathBuf; +use std::{io::Write, path::PathBuf}; +use checker; use clap::{Parser, Subcommand}; use miette::Result; @@ -29,6 +30,9 @@ enum Commands { /// What javascript runtime to compile to #[arg(short, long, default_value = "deno")] target: String, + /// Format the output javascript? + #[arg(long, default_value_t = true)] + format: bool, }, Run { file: PathBuf, @@ -51,11 +55,11 @@ pub fn transpile(content: String) -> Result { // 2. Parse the tokens into an AST let blight_ast = ast::parse(tokens)?; // 3. Type check the AST - // type_check(tree.clone())?; + checker::check_module(&blight_ast)?; // 4. Optimize the AST // optimize(tree.clone())?; // 5. Translate the AST into javascript - let js_ast = js_ast::translate(blight_ast)?; + let js_ast = js_ast::translate(&blight_ast)?; // 6. Print the JS AST let javascript = js_printer::print(js_ast); // 7. Return the javascript @@ -70,9 +74,38 @@ fn main() -> Result<()> { file, stdout, target: _, + format, } => { - let contents = std::fs::read_to_string(file.clone()).unwrap(); - let result = transpile(contents.clone())?; + let contents = match std::fs::read_to_string(file.clone()) { + Ok(contents) => contents, + Err(e) => { + eprintln!("Failed to read {}: {}", file.display(), e); + std::process::exit(1); + } + }; + + let mut result = transpile(contents.clone())?; + + if format { + let mut formatter = std::process::Command::new("deno") + .stdin(std::process::Stdio::piped()) + .stdout(std::process::Stdio::piped()) + .stderr(std::process::Stdio::inherit()) + .arg("fmt") + .arg("-") + .spawn() + .expect("Failed to execute 'deno fmt' on output"); + let mut stdin = formatter.stdin.take().expect("Failed to open stdin"); + stdin + .write_all(result.as_bytes()) + .expect("Failed to write to stdin"); + stdin.flush().expect("Failed to flush stdin"); + drop(stdin); + let out = formatter + .wait_with_output() + .expect("Failed to execute 'deno fmt' on output"); + result = String::from_utf8(out.stdout).unwrap(); + } if stdout { println!("{}", result); diff --git a/crates/js_ast/src/lib.rs b/crates/js_ast/src/lib.rs index f0f738cde7b062470fb261f949c656f770af9b8a..28685a906d0f4fa1e3083a8b6f70bc9a97e3457f 100644 --- a/crates/js_ast/src/lib.rs +++ b/crates/js_ast/src/lib.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use miette::Result; -use ast::Ast; +use ast::{Ast, Module}; mod types; pub use types::{JsExpression, JsStatement}; @@ -55,9 +55,10 @@ impl TranslateContext { .last_mut() .unwrap() .statements - .push(JsStatement::VariableDeclaration { + .push(JsStatement::Declaration { name: format!("${}", self.internal_counter), value, + is_constant: false, }); self.internal_counter += 1; JsExpression::Identifier(format!("${}", self.internal_counter - 1)) @@ -169,28 +170,18 @@ fn get_expression_handle(ast: &Ast, ctx: &mut TranslateContext) -> JsExpression fn translate_statement(ast: &Ast, ctx: &mut TranslateContext) { match ast { - Ast::ConstantDeclaration { + Ast::Declaration { name, - return_type: _, + decl_type: _, value, + is_constant, } => { let handle = get_expression_handle(value, ctx); let rename = ctx.declare_variable(name.clone()); - ctx.push(JsStatement::ConstantDeclaration { - name: rename, - value: handle, - }); - } - Ast::VariableDeclaration { - name, - return_type: _, - value, - } => { - let handle = get_expression_handle(value, ctx); - let rename = ctx.declare_variable(name.clone()); - ctx.push(JsStatement::VariableDeclaration { + ctx.push(JsStatement::Declaration { name: rename, value: handle, + is_constant: is_constant.clone(), }); } Ast::Function { @@ -226,16 +217,13 @@ fn translate_statement(ast: &Ast, ctx: &mut TranslateContext) { translate_statement(value, ctx); // I'm sorry, I just don't know how to get the original name properly... my bad match ctx.peek() { - JsStatement::Function { name, .. } - | JsStatement::VariableDeclaration { name, .. } - | JsStatement::ConstantDeclaration { name, .. } => { + JsStatement::Function { name, .. } | JsStatement::Declaration { name, .. } => { let original_name = name.split("$").next().unwrap().to_string(); - ctx.push(JsStatement::Export(Box::new( - JsStatement::ConstantDeclaration { - name: original_name, - value: JsExpression::Identifier(name.clone()), - }, - ))); + ctx.push(JsStatement::Export(Box::new(JsStatement::Declaration { + name: original_name, + value: JsExpression::Identifier(name.clone()), + is_constant: false, + }))); } _ => { panic!("Cannot make non-function public"); @@ -337,10 +325,10 @@ fn translate_statement(ast: &Ast, ctx: &mut TranslateContext) { } } -pub fn translate(_ast: Vec) -> Result> { +pub fn translate(module: &Module) -> Result> { let mut ctx = TranslateContext::new(); - for ast in _ast { + for ast in module.value.iter() { translate_statement(&ast, &mut ctx); } diff --git a/crates/js_ast/src/types.rs b/crates/js_ast/src/types.rs index 18a2788da595867d00cc1249f0cbd40f5487f3d0..3b5f176e4a51e7ccf14eb6fcf3be46c25577f8b2 100644 --- a/crates/js_ast/src/types.rs +++ b/crates/js_ast/src/types.rs @@ -33,13 +33,10 @@ pub enum JsStatement { Expression(JsExpression), Export(Box), Return(JsExpression), - VariableDeclaration { - name: String, - value: JsExpression, - }, - ConstantDeclaration { + Declaration { name: String, value: JsExpression, + is_constant: bool, }, Function { name: String, diff --git a/crates/js_printer/src/print_expression.rs b/crates/js_printer/src/print_expression.rs index ff87066c667b0ed8496173cb4fbe09422702e859..e13e3ebbda35bf9db23ae4dd38c3d8cb513c65f6 100644 --- a/crates/js_printer/src/print_expression.rs +++ b/crates/js_printer/src/print_expression.rs @@ -230,7 +230,7 @@ mod tests { assert_eq!( print_expression(&JsExpression::Function { arguments: vec!["a".to_string(), "b".to_string()], - value: vec![JsStatement::VariableDeclaration { + value: vec![JsStatement::Declaration { name: "a".to_string(), value: JsExpression::Number(1.0) }], diff --git a/crates/js_printer/src/print_statement.rs b/crates/js_printer/src/print_statement.rs index 4a9bf75b17a5f0fde0844473aad91c65dbb51b92..2f4c37399b38c214fc2e8036fbb232aaf0017234 100644 --- a/crates/js_printer/src/print_statement.rs +++ b/crates/js_printer/src/print_statement.rs @@ -7,11 +7,20 @@ pub fn print_statement(statement: &JsStatement) -> String { JsStatement::Expression(value) => format!("{};", print_expression(value)), JsStatement::Export(value) => format!("export {}", print_statement(value)), JsStatement::Return(value) => format!("return {};", print_expression(value)), - JsStatement::VariableDeclaration { name, value } => { - format!("let {}={};", name, print_expression(value)) - } - JsStatement::ConstantDeclaration { name, value } => { - format!("const {}={};", name, print_expression(value)) + JsStatement::Declaration { + name, + value, + is_constant, + } => { + format!( + "{} {}={};", + match is_constant { + true => "const", + false => "let", + }, + name, + print_expression(value) + ) } JsStatement::Function { name, @@ -66,7 +75,7 @@ mod tests { #[test] fn variable_declaration() { assert_eq!( - print_statement(&JsStatement::VariableDeclaration { + print_statement(&JsStatement::Declaration { name: "x".to_string(), value: JsExpression::Number(1.0), }), diff --git a/crates/tokenizer/src/lib.rs b/crates/tokenizer/src/lib.rs index 4892985ab5abfd83a772b786ba469e88436e6a7c..a35ad44dd5d8122748a865188c70b94544a9fb3a 100644 --- a/crates/tokenizer/src/lib.rs +++ b/crates/tokenizer/src/lib.rs @@ -43,6 +43,42 @@ pub enum Token { Operator(Operator), } +impl std::fmt::Display for Token { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let token = match self { + Token::Identifier(_) => "an identifier".to_string(), + Token::Number(n) => n.to_string(), + Token::String(s) => format!("\"{}\"", s), + Token::BuiltIn(_) => "a builtin identifier".to_string(), + Token::Comment(_) => "a comment".to_string(), + Token::DocComment(_) => "a documentation comment".to_string(), + Token::True => "true".to_string(), + Token::False => "false".to_string(), + Token::Let => "let".to_string(), + Token::Var => "var".to_string(), + Token::If => "if".to_string(), + Token::Else => "else".to_string(), + Token::Return => "return".to_string(), + Token::Pub => "pub".to_string(), + Token::Function => "fn".to_string(), + Token::RightArrow => "->".to_string(), + Token::Comma => ",".to_string(), + Token::OpenParanthesis => "(".to_string(), + Token::ClosedParanthesis => ")".to_string(), + Token::OpenBracket => "{".to_string(), + Token::ClosedBracket => "}".to_string(), + Token::Colon => ":".to_string(), + Token::Equals => "=".to_string(), + Token::Semicolon => ";".to_string(), + Token::Operator(o) => o.clone().to_string(), + }; + + write!(f, "{}", token) + } +} + + + pub fn tokenize(content: String) -> Result> { let mut tokens: Vec = Vec::new(); let mut chars = content.chars().enumerate().peekable(); diff --git a/examples/basics/control.blight b/examples/basics/control.blight index 1428905a5fddb419fb987256783c401c956355d2..f6e3bdb1db079dc14869607c8fc2821eee7a89f2 100644 --- a/examples/basics/control.blight +++ b/examples/basics/control.blight @@ -1,4 +1,4 @@ -let print: any = @raw("console.log"); +let print = @raw("console.log"); let x: bool = true; diff --git a/examples/basics/expressions.blight b/examples/basics/expressions.blight index fbc8e4c4c024dff1abf958045fd7d5a3c189bd7c..4897a92481c947df2cefd5171363c5d919241e9f 100644 --- a/examples/basics/expressions.blight +++ b/examples/basics/expressions.blight @@ -7,5 +7,5 @@ let x: int = 5 + { y }; -let print: any = @raw("console.log"); +let print = @raw("console.log"); print(x); // 10 diff --git a/examples/basics/fib.blight b/examples/basics/fib.blight index 898f001d4f163a3b4142a38a64a86fd2393b9181..bfa4b5623183aa460e1f0b79e0988f660ab4def4 100644 --- a/examples/basics/fib.blight +++ b/examples/basics/fib.blight @@ -8,5 +8,5 @@ pub fn fib(n: int) -> int { } } -let print: any = @raw("console.log"); +let print = @raw("console.log"); print(fib(10)); diff --git a/examples/basics/functions.blight b/examples/basics/functions.blight index 58cd31caa9d8c9c49aadd8609bc9ccc62bc36eb2..37ca9d3a2dce9143b9e7b2dbd50819abff151942 100644 --- a/examples/basics/functions.blight +++ b/examples/basics/functions.blight @@ -4,5 +4,5 @@ fn bingus(x: int, y: int) -> int { let result: int = bingus(10, 25); -let print: any = @raw("console.log"); +let print = @raw("console.log"); print(result); diff --git a/examples/basics/operations.blight b/examples/basics/operations.blight index 85ee1283b38b61b6840f20d8dd6f8c206d8cf7c9..55dc5693ebb9d507fd598284e1510811f34cbc03 100644 --- a/examples/basics/operations.blight +++ b/examples/basics/operations.blight @@ -1,4 +1,4 @@ let a: int = 10 - 2 / 4 * 15; -let print: any = @raw("console.log"); +let print = @raw("console.log"); print(a); diff --git a/examples/basics/shadowing.blight b/examples/basics/shadowing.blight index 2a8514581e8a102a5f67b44c22f825aca3fd9252..3e96605fa4d98e020ae275232d4cc06ed958c9c0 100644 --- a/examples/basics/shadowing.blight +++ b/examples/basics/shadowing.blight @@ -1,4 +1,4 @@ -let print: any = @raw("console.log"); +let print = @raw("console.log"); let x: int = 0; let x: int = 1; diff --git a/examples/basics/variables.blight b/examples/basics/variables.blight index 3bfe757ddba318fa7e40620b6a4bbbd6c3f2cf45..302be86a6474de450a084ae10406e333f2afd1b5 100644 --- a/examples/basics/variables.blight +++ b/examples/basics/variables.blight @@ -6,5 +6,5 @@ let a: int = 0; let b: float = 0; let c: bigint = 0; -let print: any = @raw("console.log"); +let print = @raw("console.log"); print(x); diff --git a/examples/basics/weird.blight b/examples/basics/weird.blight index a10c1ec7a2f55dbbe68e90ab93503ceefd4c91aa..80b5ea000738ae9763f383f35a18b2a665448958 100644 --- a/examples/basics/weird.blight +++ b/examples/basics/weird.blight @@ -9,6 +9,6 @@ fn bingus(y: bool) -> int { x } -let print: any = @raw("console.log"); +let print = @raw("console.log"); print(bingus(true)); print(bingus(false)); diff --git a/examples/interop/deno.blight b/examples/interop/deno.blight index 9f6b1157fa6bb3f64d7f1ffbdc0f086372559925..1b5fd3af6cad1c63f41f5f41f55c17d25bc98de0 100644 --- a/examples/interop/deno.blight +++ b/examples/interop/deno.blight @@ -1,4 +1,4 @@ -let writeTextFile: any = @raw("Deno.writeTextFile"); +let writeTextFile = @raw("Deno.writeTextFile"); fn x() -> string { "hello"