diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 36b87aa..e568a8f 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -32,6 +32,8 @@ use crate::build::scope::Scope; use crate::build::Val; use crate::error::{BuildError, ErrorType::TypeFail}; +use self::walk::Walker; + pub mod printer; pub mod rewrite; pub mod typecheck; @@ -272,8 +274,8 @@ value_enum!( ); impl Shape { - pub fn merge(&self, compare: &Shape) -> Option { - match (self, compare) { + pub fn merge(&self, right: &Shape) -> Option { + match (self, right) { (Shape::Str(_), Shape::Str(_)) | (Shape::Symbol(_), Shape::Symbol(_)) | (Shape::Boolean(_), Shape::Boolean(_)) @@ -775,7 +777,7 @@ fn normalize_path(p: PathBuf) -> PathBuf { return normalized; } -impl walk::Walker for Rewriter { +impl Walker for Rewriter { fn walk_statement_list(&mut self, stmts: Vec<&mut Statement>) { for v in stmts { self.walk_statement(v); @@ -1046,12 +1048,26 @@ impl Expression { CastType::Float => Shape::Float(PositionedItem::new(0.0, def.pos.clone())), CastType::Bool => Shape::Boolean(PositionedItem::new(true, def.pos.clone())), }, - Expression::Import(def) => { - // FIXME(jwall): What should this do? - Shape::Symbol(PositionedItem::new( - def.path.fragment.clone(), - def.path.pos.clone(), - )) + Expression::Import(def) => Shape::Symbol(PositionedItem::new( + def.path.fragment.clone(), + def.path.pos.clone(), + )), + Expression::Binary(def) => { + let left_shape = def.left.derive_shape()?; + let right_shape = def.right.derive_shape()?; + match left_shape.merge(&right_shape) { + Some(shape) => shape, + None => { + return Err(BuildError::new( + format!( + "Expected {} value on right hand side of expression but got: {}", + left_shape.type_name(), + right_shape.type_name() + ), + TypeFail, + )); + } + } } _ => Shape::Empty(Position::new(0, 0, 0)), }; diff --git a/src/ast/rewrite.rs b/src/ast/rewrite.rs index 9fd33c8..9153ba7 100644 --- a/src/ast/rewrite.rs +++ b/src/ast/rewrite.rs @@ -13,7 +13,7 @@ // limitations under the License. use std::path::PathBuf; -use crate::ast::walk::{Visitor, Walker}; +use crate::ast::walk::Visitor; use crate::ast::Expression; pub struct Rewriter { diff --git a/src/ast/test.rs b/src/ast/test.rs index efb626e..e508881 100644 --- a/src/ast/test.rs +++ b/src/ast/test.rs @@ -154,6 +154,10 @@ fn derive_shape_expressions() { "bool(\"true\");", Shape::Boolean(PositionedItem::new(true, Position::new(0, 0, 0))), ), + ( + "1 + 1;", + Shape::Int(PositionedItem::new(1, Position::new(1, 1, 0))), + ), ]; for (expr, shape) in expr_cases { diff --git a/src/ast/typecheck/mod.rs b/src/ast/typecheck/mod.rs index a2b8717..aabff19 100644 --- a/src/ast/typecheck/mod.rs +++ b/src/ast/typecheck/mod.rs @@ -13,7 +13,7 @@ // limitations under the License. //! Implements typechecking for the parsed ucg AST. - +// FIXME(jwall): This probably just needs to disappear now. use std::collections::BTreeMap; use crate::ast::walk::Visitor; diff --git a/src/build/opcode/environment.rs b/src/build/opcode/environment.rs index d4030db..5e8dc66 100644 --- a/src/build/opcode/environment.rs +++ b/src/build/opcode/environment.rs @@ -35,6 +35,7 @@ where Stderr: Write + Clone, { pub val_cache: BTreeMap>, + // TODO implement a shape cache here. pub op_cache: cache::Ops, pub converter_registry: ConverterRegistry, pub importer_registry: ImporterRegistry, diff --git a/src/build/opcode/translate.rs b/src/build/opcode/translate.rs index aed360c..016671a 100644 --- a/src/build/opcode/translate.rs +++ b/src/build/opcode/translate.rs @@ -18,7 +18,7 @@ use crate::ast::rewrite::Rewriter; use crate::ast::walk::Walker; use crate::ast::{ BinaryExprType, BinaryOpDef, Expression, FormatArgs, FuncOpDef, Position, PositionedItem, - SelectDef, Statement, TemplatePart, Token, TokenType, Value, + SelectDef, Shape, Statement, TemplatePart, Token, TokenType, Value, }; use crate::build::format::{ExpressionTemplate, SimpleTemplate, TemplateParser}; use crate::build::opcode::Primitive; @@ -30,6 +30,7 @@ pub struct AST(); pub struct OpsMap { pub ops: Vec, pub pos: Vec, + pub shape_map: BTreeMap, pub links: BTreeMap, } @@ -38,6 +39,8 @@ impl OpsMap { OpsMap { ops: Vec::new(), pos: Vec::new(), + // TODO(jwall): Populate shapes when translating into opcodes. + shape_map: BTreeMap::new(), links: BTreeMap::new(), } }