diff --git a/valuescript_compiler/src/compile_enum_value.rs b/valuescript_compiler/src/compile_enum_value.rs deleted file mode 100644 index c179ef3..0000000 --- a/valuescript_compiler/src/compile_enum_value.rs +++ /dev/null @@ -1,63 +0,0 @@ -use swc_common::Spanned; - -use crate::{ - asm::{Number, Object, Value}, - diagnostic::DiagnosticReporter, - module_compiler::ModuleCompiler, - static_eval_expr::static_eval_expr, -}; - -pub fn compile_enum_value(mc: &mut ModuleCompiler, ts_enum: &swc_ecma_ast::TsEnumDecl) -> Value { - let mut properties = Vec::<(Value, Value)>::new(); - let mut next_default_id: Option = Some(0.0); - - for member in &ts_enum.members { - let key = match &member.id { - swc_ecma_ast::TsEnumMemberId::Ident(ident) => ident.sym.to_string(), - swc_ecma_ast::TsEnumMemberId::Str(str) => str.value.to_string(), - }; - - let init_value = match &member.init { - Some(init) => match static_eval_expr(mc, init) { - Some(init_value) => match init_value { - Value::Number(Number(n)) => { - next_default_id = Some(n + 1.0); - Some(Value::Number(Number(n))) - } - Value::String(_) => Some(init_value), - _ => None, - }, - None => { - mc.internal_error(init.span(), "Static eval failed"); - - None - } - }, - None => None, - }; - - let value = match init_value { - Some(value) => value, - None => { - let id = match next_default_id { - Some(id) => id, - None => { - mc.error(member.span, "Missing required initializer"); - - 0.0 - } - }; - - let value = Value::Number(Number(id)); - next_default_id = Some(id + 1.0); - - value - } - }; - - properties.push((Value::String(key.clone()), value.clone())); - properties.push((value, Value::String(key))); - } - - Value::Object(Box::new(Object { properties })) -} diff --git a/valuescript_compiler/src/function_compiler.rs b/valuescript_compiler/src/function_compiler.rs index 1e7d1de..7adf12a 100644 --- a/valuescript_compiler/src/function_compiler.rs +++ b/valuescript_compiler/src/function_compiler.rs @@ -8,7 +8,6 @@ use crate::asm::{ Builtin, Definition, DefinitionContent, FnLine, Function, Instruction, Label, Pointer, Register, Value, }; -use crate::compile_enum_value::compile_enum_value; use crate::diagnostic::{Diagnostic, DiagnosticContainer, DiagnosticLevel, DiagnosticReporter}; use crate::expression_compiler::CompiledExpression; use crate::expression_compiler::ExpressionCompiler; @@ -1203,7 +1202,7 @@ impl<'a> FunctionCompiler<'a> { } }; - let enum_value = compile_enum_value(self.mc, ts_enum); + let enum_value = self.mc.compile_enum_value(ts_enum); self.definitions.push(Definition { pointer, diff --git a/valuescript_compiler/src/lib.rs b/valuescript_compiler/src/lib.rs index fc28831..52ab667 100644 --- a/valuescript_compiler/src/lib.rs +++ b/valuescript_compiler/src/lib.rs @@ -2,7 +2,6 @@ pub mod asm; mod assembler; pub mod assembly_parser; mod compile; -mod compile_enum_value; mod constants; mod diagnostic; mod expression_compiler; @@ -18,7 +17,6 @@ mod optimization; mod resolve_path; mod scope; mod scope_analysis; -mod static_eval_expr; mod target_accessor; mod visit_pointers; diff --git a/valuescript_compiler/src/module_compiler.rs b/valuescript_compiler/src/module_compiler.rs index 6f9f793..b2507cf 100644 --- a/valuescript_compiler/src/module_compiler.rs +++ b/valuescript_compiler/src/module_compiler.rs @@ -5,20 +5,19 @@ use swc_common::errors::{DiagnosticBuilder, Emitter}; use swc_common::{errors::Handler, FileName, SourceMap, Spanned}; use swc_ecma_ast::EsVersion; use swc_ecma_parser::{Syntax, TsConfig}; +use valuescript_vm::operations::to_i32; use crate::asm::{ - Class, Definition, DefinitionContent, FnLine, Function, Instruction, Lazy, Module, Object, - Pointer, Register, Value, + Array, Builtin, Class, Definition, DefinitionContent, FnLine, Function, Instruction, Lazy, + Module, Number, Object, Pointer, Register, Value, }; -use crate::compile_enum_value::compile_enum_value; use crate::diagnostic::{Diagnostic, DiagnosticContainer, DiagnosticReporter}; -use crate::expression_compiler::{CompiledExpression, ExpressionCompiler}; +use crate::expression_compiler::{value_from_literal, CompiledExpression, ExpressionCompiler}; use crate::function_compiler::{FunctionCompiler, Functionish}; use crate::ident::Ident; use crate::name_allocator::{ident_from_str, NameAllocator}; use crate::scope::OwnerId; use crate::scope_analysis::ScopeAnalysis; -use crate::static_eval_expr::static_eval_expr; struct DiagnosticCollector { diagnostics: Arc>>, @@ -181,11 +180,12 @@ impl ModuleCompiler { ExportDefaultDecl(edd) => self.compile_export_default_decl(edd), ExportDefaultExpr(ede) => { let value = match &*ede.expr { + // TODO: Just do identifiers in compile_expr swc_ecma_ast::Expr::Ident(ident) => self .scope_analysis .lookup(&Ident::from_swc_ident(ident)) .map(|name| name.value.clone()), - expr => static_eval_expr(self, expr), + expr => self.compile_expr(expr), }; match value { @@ -284,7 +284,7 @@ impl ModuleCompiler { }; if let (Some(ident), Some(init)) = (ident, init) { - let value_opt = static_eval_expr(self, init); + let value_opt = self.compile_expr(init); let value = match value_opt { Some(value) => value, @@ -386,7 +386,7 @@ impl ModuleCompiler { )); } - let enum_value = compile_enum_value(self, ts_enum); + let enum_value = self.compile_enum_value(ts_enum); self.module.definitions.push(Definition { pointer, @@ -869,7 +869,7 @@ impl ModuleCompiler { let name = match &method.key { swc_ecma_ast::PropName::Ident(ident) => Value::String(ident.sym.to_string()), swc_ecma_ast::PropName::Computed(computed) => { - let value_opt = static_eval_expr(self, &computed.expr); + let value_opt = self.compile_expr(&computed.expr); match value_opt { None => { @@ -938,4 +938,233 @@ impl ModuleCompiler { defn_name } + + pub fn compile_enum_value(&mut self, ts_enum: &swc_ecma_ast::TsEnumDecl) -> Value { + let mut properties = Vec::<(Value, Value)>::new(); + let mut next_default_id: Option = Some(0.0); + + for member in &ts_enum.members { + let key = match &member.id { + swc_ecma_ast::TsEnumMemberId::Ident(ident) => ident.sym.to_string(), + swc_ecma_ast::TsEnumMemberId::Str(str) => str.value.to_string(), + }; + + let init_value = match &member.init { + Some(init) => match self.compile_expr(init) { + Some(init_value) => match init_value { + Value::Number(Number(n)) => { + next_default_id = Some(n + 1.0); + Some(Value::Number(Number(n))) + } + Value::String(_) => Some(init_value), + _ => None, + }, + None => { + self.internal_error(init.span(), "Static eval failed"); + None + } + }, + None => None, + }; + + let value = match init_value { + Some(value) => value, + None => { + let id = match next_default_id { + Some(id) => id, + None => { + self.error(member.span, "Missing required initializer"); + 0.0 + } + }; + + let value = Value::Number(Number(id)); + next_default_id = Some(id + 1.0); + + value + } + }; + + properties.push((Value::String(key.clone()), value.clone())); + properties.push((value, Value::String(key))); + } + + Value::Object(Box::new(Object { properties })) + } + + pub fn compile_expr(&mut self, expr: &swc_ecma_ast::Expr) -> Option { + let symbol_iterator_opt = as_symbol_iterator(expr); + + if symbol_iterator_opt.is_some() { + return symbol_iterator_opt; + } + + match expr { + swc_ecma_ast::Expr::Lit(lit) => match value_from_literal(lit) { + Ok(value) => Some(value), + _ => None, + }, + swc_ecma_ast::Expr::Array(array) => { + let mut values = Vec::::new(); + + for item in &array.elems { + values.push(match item { + Some(item) => { + if item.spread.is_some() { + return None; + } + + self.compile_expr(&item.expr)? + } + None => Value::Void, + }); + } + + Some(Value::Array(Box::new(Array { values }))) + } + swc_ecma_ast::Expr::Object(object) => { + let mut properties = Vec::<(Value, Value)>::new(); + + for prop in &object.props { + let (key, value) = match prop { + swc_ecma_ast::PropOrSpread::Spread(_) => return None, + swc_ecma_ast::PropOrSpread::Prop(prop) => match &**prop { + swc_ecma_ast::Prop::Shorthand(_) => return None, + swc_ecma_ast::Prop::KeyValue(kv) => { + let key = match &kv.key { + swc_ecma_ast::PropName::Ident(ident) => Value::String(ident.sym.to_string()), + swc_ecma_ast::PropName::Str(str) => Value::String(str.value.to_string()), + swc_ecma_ast::PropName::Num(num) => Value::Number(Number(num.value)), + swc_ecma_ast::PropName::Computed(computed) => { + self.compile_expr(&computed.expr)? + } + swc_ecma_ast::PropName::BigInt(bi) => Value::BigInt(bi.value.clone()), + }; + + let value = self.compile_expr(&kv.value)?; + + (key, value) + } + swc_ecma_ast::Prop::Assign(_) => return None, + swc_ecma_ast::Prop::Getter(_) => return None, + swc_ecma_ast::Prop::Setter(_) => return None, + swc_ecma_ast::Prop::Method(_) => return None, + }, + }; + + properties.push((key, value)); + } + + Some(Value::Object(Box::new(Object { properties }))) + } + swc_ecma_ast::Expr::This(_) => None, + swc_ecma_ast::Expr::Fn(_) => None, + swc_ecma_ast::Expr::Update(_) => None, + swc_ecma_ast::Expr::Assign(_) => None, + swc_ecma_ast::Expr::SuperProp(_) => None, + swc_ecma_ast::Expr::Call(_) => None, + swc_ecma_ast::Expr::New(_) => None, + swc_ecma_ast::Expr::Ident(ident) => match self + .scope_analysis + .lookup(&Ident::from_swc_ident(ident)) + .map(|name| name.value.clone()) + { + Some(Value::Pointer(p)) => self.constants_map.get(&p).cloned(), + Some(value) => Some(value), + None => None, + }, + swc_ecma_ast::Expr::TaggedTpl(_) => None, + swc_ecma_ast::Expr::Arrow(_) => None, + swc_ecma_ast::Expr::Class(_) => None, + swc_ecma_ast::Expr::Yield(_) => None, + swc_ecma_ast::Expr::MetaProp(_) => None, + swc_ecma_ast::Expr::Await(_) => None, + swc_ecma_ast::Expr::JSXMember(_) => None, + swc_ecma_ast::Expr::JSXNamespacedName(_) => None, + swc_ecma_ast::Expr::JSXEmpty(_) => None, + swc_ecma_ast::Expr::JSXElement(_) => None, + swc_ecma_ast::Expr::JSXFragment(_) => None, + swc_ecma_ast::Expr::TsInstantiation(_) => None, + swc_ecma_ast::Expr::PrivateName(_) => None, + swc_ecma_ast::Expr::OptChain(_) => None, + swc_ecma_ast::Expr::Invalid(_) => None, + swc_ecma_ast::Expr::Member(_) => None, + swc_ecma_ast::Expr::Cond(_) => None, + swc_ecma_ast::Expr::Unary(unary) => match unary.op { + swc_ecma_ast::UnaryOp::Minus => match self.compile_expr(&unary.arg)? { + Value::Number(Number(x)) => Some(Value::Number(Number(-x))), + Value::BigInt(bi) => Some(Value::BigInt(-bi)), + _ => None, + }, + swc_ecma_ast::UnaryOp::Plus => match self.compile_expr(&unary.arg)? { + Value::Number(Number(x)) => Some(Value::Number(Number(x))), + Value::BigInt(bi) => Some(Value::BigInt(bi)), + _ => None, + }, + swc_ecma_ast::UnaryOp::Bang => None, + swc_ecma_ast::UnaryOp::Tilde => match self.compile_expr(&unary.arg)? { + Value::Number(Number(x)) => Some(Value::Number(Number(!to_i32(x) as f64))), + Value::BigInt(bi) => Some(Value::BigInt(!bi)), + _ => None, + }, + swc_ecma_ast::UnaryOp::TypeOf => None, + swc_ecma_ast::UnaryOp::Void => None, + swc_ecma_ast::UnaryOp::Delete => None, + }, + swc_ecma_ast::Expr::Bin(_) => None, + swc_ecma_ast::Expr::Seq(seq) => { + let mut last = Value::Void; + + for expr in &seq.exprs { + last = self.compile_expr(expr)?; + } + + Some(last) + } + swc_ecma_ast::Expr::Tpl(tpl) => 'b: { + let len = tpl.exprs.len(); + assert_eq!(tpl.quasis.len(), len + 1); + + if len == 0 { + break 'b Some(Value::String(tpl.quasis[0].raw.to_string())); + } + + None // TODO + } + swc_ecma_ast::Expr::Paren(paren) => self.compile_expr(&paren.expr), + swc_ecma_ast::Expr::TsTypeAssertion(tta) => self.compile_expr(&tta.expr), + swc_ecma_ast::Expr::TsConstAssertion(tca) => self.compile_expr(&tca.expr), + swc_ecma_ast::Expr::TsNonNull(tnn) => self.compile_expr(&tnn.expr), + swc_ecma_ast::Expr::TsAs(ta) => self.compile_expr(&ta.expr), + } + } +} + +fn as_symbol_iterator(expr: &swc_ecma_ast::Expr) -> Option { + let member_expr = match expr { + swc_ecma_ast::Expr::Member(member_expr) => member_expr, + _ => return None, + }; + + match &*member_expr.obj { + swc_ecma_ast::Expr::Ident(ident) => { + if ident.sym.to_string() != "Symbol" { + return None; + } + } + _ => return None, + }; + + match &member_expr.prop { + swc_ecma_ast::MemberProp::Ident(ident) => { + if ident.sym.to_string() != "iterator" { + return None; + } + } + _ => return None, + } + + Some(Value::Builtin(Builtin { + name: "SymbolIterator".to_string(), + })) } diff --git a/valuescript_compiler/src/static_eval_expr.rs b/valuescript_compiler/src/static_eval_expr.rs deleted file mode 100644 index c520fbb..0000000 --- a/valuescript_compiler/src/static_eval_expr.rs +++ /dev/null @@ -1,182 +0,0 @@ -use valuescript_vm::operations::to_i32; - -use crate::{ - asm::{Array, Builtin, Number, Object, Value}, - expression_compiler::value_from_literal, - ident::Ident, - module_compiler::ModuleCompiler, -}; - -pub fn static_eval_expr(mc: &ModuleCompiler, expr: &swc_ecma_ast::Expr) -> Option { - let symbol_iterator_opt = as_symbol_iterator(expr); - - if symbol_iterator_opt.is_some() { - return symbol_iterator_opt; - } - - match expr { - swc_ecma_ast::Expr::Lit(lit) => match value_from_literal(lit) { - Ok(value) => Some(value), - _ => None, - }, - swc_ecma_ast::Expr::Array(array) => { - let mut values = Vec::::new(); - - for item in &array.elems { - values.push(match item { - Some(item) => { - if item.spread.is_some() { - return None; - } - - static_eval_expr(mc, &item.expr)? - } - None => Value::Void, - }); - } - - Some(Value::Array(Box::new(Array { values }))) - } - swc_ecma_ast::Expr::Object(object) => { - let mut properties = Vec::<(Value, Value)>::new(); - - for prop in &object.props { - let (key, value) = match prop { - swc_ecma_ast::PropOrSpread::Spread(_) => return None, - swc_ecma_ast::PropOrSpread::Prop(prop) => match &**prop { - swc_ecma_ast::Prop::Shorthand(_) => return None, - swc_ecma_ast::Prop::KeyValue(kv) => { - let key = match &kv.key { - swc_ecma_ast::PropName::Ident(ident) => Value::String(ident.sym.to_string()), - swc_ecma_ast::PropName::Str(str) => Value::String(str.value.to_string()), - swc_ecma_ast::PropName::Num(num) => Value::Number(Number(num.value)), - swc_ecma_ast::PropName::Computed(computed) => static_eval_expr(mc, &computed.expr)?, - swc_ecma_ast::PropName::BigInt(bi) => Value::BigInt(bi.value.clone()), - }; - - let value = static_eval_expr(mc, &kv.value)?; - - (key, value) - } - swc_ecma_ast::Prop::Assign(_) => return None, - swc_ecma_ast::Prop::Getter(_) => return None, - swc_ecma_ast::Prop::Setter(_) => return None, - swc_ecma_ast::Prop::Method(_) => return None, - }, - }; - - properties.push((key, value)); - } - - Some(Value::Object(Box::new(Object { properties }))) - } - swc_ecma_ast::Expr::This(_) => None, - swc_ecma_ast::Expr::Fn(_) => None, - swc_ecma_ast::Expr::Update(_) => None, - swc_ecma_ast::Expr::Assign(_) => None, - swc_ecma_ast::Expr::SuperProp(_) => None, - swc_ecma_ast::Expr::Call(_) => None, - swc_ecma_ast::Expr::New(_) => None, - swc_ecma_ast::Expr::Ident(ident) => match mc - .scope_analysis - .lookup(&Ident::from_swc_ident(ident)) - .map(|name| name.value.clone()) - { - Some(Value::Pointer(p)) => mc.constants_map.get(&p).cloned(), - Some(value) => Some(value), - None => None, - }, - swc_ecma_ast::Expr::TaggedTpl(_) => None, - swc_ecma_ast::Expr::Arrow(_) => None, - swc_ecma_ast::Expr::Class(_) => None, - swc_ecma_ast::Expr::Yield(_) => None, - swc_ecma_ast::Expr::MetaProp(_) => None, - swc_ecma_ast::Expr::Await(_) => None, - swc_ecma_ast::Expr::JSXMember(_) => None, - swc_ecma_ast::Expr::JSXNamespacedName(_) => None, - swc_ecma_ast::Expr::JSXEmpty(_) => None, - swc_ecma_ast::Expr::JSXElement(_) => None, - swc_ecma_ast::Expr::JSXFragment(_) => None, - swc_ecma_ast::Expr::TsInstantiation(_) => None, - swc_ecma_ast::Expr::PrivateName(_) => None, - swc_ecma_ast::Expr::OptChain(_) => None, - swc_ecma_ast::Expr::Invalid(_) => None, - swc_ecma_ast::Expr::Member(_) => None, - swc_ecma_ast::Expr::Cond(_) => None, - swc_ecma_ast::Expr::Unary(unary) => match unary.op { - swc_ecma_ast::UnaryOp::Minus => match static_eval_expr(mc, &unary.arg)? { - Value::Number(Number(x)) => Some(Value::Number(Number(-x))), - Value::BigInt(bi) => Some(Value::BigInt(-bi)), - _ => None, - }, - swc_ecma_ast::UnaryOp::Plus => match static_eval_expr(mc, &unary.arg)? { - Value::Number(Number(x)) => Some(Value::Number(Number(x))), - Value::BigInt(bi) => Some(Value::BigInt(bi)), - _ => None, - }, - swc_ecma_ast::UnaryOp::Bang => None, - swc_ecma_ast::UnaryOp::Tilde => match static_eval_expr(mc, &unary.arg)? { - Value::Number(Number(x)) => Some(Value::Number(Number(!to_i32(x) as f64))), - Value::BigInt(bi) => Some(Value::BigInt(!bi)), - _ => None, - }, - swc_ecma_ast::UnaryOp::TypeOf => None, - swc_ecma_ast::UnaryOp::Void => None, - swc_ecma_ast::UnaryOp::Delete => None, - }, - swc_ecma_ast::Expr::Bin(_) => None, - swc_ecma_ast::Expr::Seq(seq) => { - let mut last = Value::Void; - - for expr in &seq.exprs { - last = static_eval_expr(mc, expr)?; - } - - Some(last) - } - swc_ecma_ast::Expr::Tpl(tpl) => 'b: { - let len = tpl.exprs.len(); - assert_eq!(tpl.quasis.len(), len + 1); - - if len == 0 { - break 'b Some(Value::String(tpl.quasis[0].raw.to_string())); - } - - None // TODO - } - swc_ecma_ast::Expr::Paren(paren) => static_eval_expr(mc, &paren.expr), - swc_ecma_ast::Expr::TsTypeAssertion(tta) => static_eval_expr(mc, &tta.expr), - swc_ecma_ast::Expr::TsConstAssertion(tca) => static_eval_expr(mc, &tca.expr), - swc_ecma_ast::Expr::TsNonNull(tnn) => static_eval_expr(mc, &tnn.expr), - swc_ecma_ast::Expr::TsAs(ta) => static_eval_expr(mc, &ta.expr), - } -} - -fn as_symbol_iterator(expr: &swc_ecma_ast::Expr) -> Option { - let member_expr = match expr { - swc_ecma_ast::Expr::Member(member_expr) => member_expr, - _ => return None, - }; - - match &*member_expr.obj { - swc_ecma_ast::Expr::Ident(ident) => { - if ident.sym.to_string() != "Symbol" { - return None; - } - } - _ => return None, - }; - - match &member_expr.prop { - swc_ecma_ast::MemberProp::Ident(ident) => { - if ident.sym.to_string() != "iterator" { - return None; - } - } - _ => return None, - } - - Some(Value::Builtin(Builtin { - name: "SymbolIterator".to_string(), - })) -}