diff --git a/fine/src/compiler.rs b/fine/src/compiler.rs index 18ba5f02..0c986125 100644 --- a/fine/src/compiler.rs +++ b/fine/src/compiler.rs @@ -42,7 +42,6 @@ pub enum Instruction { StoreModule(usize), StringAdd, Dup, - NewObject(usize), } pub enum Export { @@ -489,7 +488,6 @@ fn compile_binary_expression(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR { Declaration::ExternFunction { .. } => Instruction::Panic, Declaration::Function { .. } => Instruction::Panic, - Declaration::Class { .. } => Instruction::Panic, }; c.push(instruction); } @@ -547,23 +545,6 @@ fn compile_identifier_expression(c: &mut Compiler, t: TreeRef, tree: &Tree) -> O Instruction::LoadFunction(index) } Declaration::ExternFunction { id, .. } => Instruction::LoadExternFunction(id.id()), - Declaration::Class { declaration, .. } => { - let key = FunctionKey { tree: *declaration }; - let index = match c.function_bindings.get(&key) { - Some(index) => *index, - None => { - let tree = &c.syntax[*declaration]; - compiler_assert_eq!(c, t, tree.kind, TreeKind::ClassDecl); - - compile_class_declaration(c, t, tree, false)?; - - *c.function_bindings - .get(&key) - .expect("did not compile the class constructor!") - } - }; - Instruction::LoadFunction(index) - } }; c.push(instruction); @@ -724,58 +705,13 @@ fn compile_function_declaration(c: &mut Compiler, t: TreeRef, tree: &Tree, gen_v OK } -fn compile_class_declaration(c: &mut Compiler, t: TreeRef, tree: &Tree, gen_value: bool) -> CR { - // Only compile a given function once. - // Classes get compiled as constructor functions which get called. - let fk = FunctionKey { tree: t }; - if !c.function_bindings.contains_key(&fk) { - let name = tree.nth_token(1)?; - - let field_count = tree.children.len() - 2; - - let function_index = c.temp_functions.len(); - c.temp_functions.push(None); - - c.pending_functions.push(( - fk.clone(), - function_index, - Function::new(name.as_str(), field_count), - )); - c.function_bindings.insert(fk, function_index); - c.module - .exports - .insert(name.to_string(), Export::Function(function_index)); - } - - if gen_value { - c.push(Instruction::PushNothing); - } - - OK -} - fn compile_function(c: &mut Compiler, t: TreeRef) -> CR { let tree = &c.syntax[t]; - match tree.kind { - TreeKind::FunctionDecl => { - let block = tree.child_of_kind(c.syntax, TreeKind::Block)?; - compile_expression(c, block); - } - TreeKind::ClassDecl => { - let count = tree.children_of_kind(c.syntax, TreeKind::FieldDecl).count(); - for i in 0..count { - c.push(Instruction::LoadArgument(count - 1 - i)); - } - - let name = tree.nth_token(1)?.as_str(); - let name_index = c.add_string(name.to_string()); - c.push(Instruction::PushString(name_index)); - c.push(Instruction::NewObject(count)); - } - _ => ice!(c, t, "what is this tree doing in compile_function?"), - } + let block = tree.child_of_kind(c.syntax, TreeKind::Block)?; + compile_expression(c, block); c.push(Instruction::Return); + OK } diff --git a/fine/src/parser.rs b/fine/src/parser.rs index f572f045..68bdf198 100644 --- a/fine/src/parser.rs +++ b/fine/src/parser.rs @@ -125,10 +125,8 @@ pub enum TreeKind { BinaryExpression, Block, CallExpression, - ClassDecl, ConditionalExpression, ExpressionStatement, - FieldDecl, File, ForStatement, FunctionDecl, @@ -147,9 +145,6 @@ pub enum TreeKind { TypeParameter, TypeParameterList, UnaryExpression, - FieldList, - NewObjectExpression, - FieldValue, } pub struct Tree<'a> { @@ -188,17 +183,14 @@ impl<'a> Tree<'a> { }) } - pub fn children_of_kind<'b>( - &'b self, - s: &'b SyntaxTree, - kind: TreeKind, - ) -> impl Iterator + 'b { - self.child_trees() - .filter_map(move |t| if s[t].kind == kind { Some(t) } else { None }) - } - pub fn child_of_kind(&self, s: &SyntaxTree, kind: TreeKind) -> Option { - self.children_of_kind(&s, kind).next() + self.children + .iter() + .filter_map(|c| match c { + Child::Tree(t) => Some(*t), + _ => None, + }) + .find(|c| s[*c].kind == kind) } pub fn child_tree_of_kind<'b>( @@ -408,10 +400,6 @@ impl<'a> CParser<'a> { self.error(error); } - fn expect_start(&mut self, kind: TokenKind) { - assert!(self.eat(kind)); - } - fn advance_with_error(&mut self, error: T) -> MarkClosed where T: Into, @@ -510,7 +498,6 @@ fn file(p: &mut CParser) { while !p.eof() { match p.peek() { TokenKind::Fun => function(p), - TokenKind::Class => class(p), _ => statement(p), } } @@ -518,9 +505,10 @@ fn file(p: &mut CParser) { } fn function(p: &mut CParser) { + assert!(p.at(TokenKind::Fun)); let m = p.start(); - p.expect_start(TokenKind::Fun); + p.expect(TokenKind::Fun, "expected a function to start with 'fun'"); p.expect(TokenKind::Identifier, "expected a function name"); if p.at(TokenKind::LeftParen) { param_list(p); @@ -535,40 +523,11 @@ fn function(p: &mut CParser) { p.end(m, TreeKind::FunctionDecl); } -fn class(p: &mut CParser) { - let m = p.start(); - - p.expect_start(TokenKind::Class); - p.expect(TokenKind::Identifier, "expected a class name"); - if p.eat(TokenKind::LeftBrace) { - while !p.at(TokenKind::RightBrace) && !p.eof() { - field_decl(p); - } - } - p.expect(TokenKind::RightBrace, "expected a class to end with a '}'"); - - p.end(m, TreeKind::ClassDecl); -} - -fn field_decl(p: &mut CParser) { - let m = p.start(); - - p.expect(TokenKind::Identifier, "expected a field name"); - if p.eat(TokenKind::Colon) { - type_expr(p); - } - p.expect( - TokenKind::Semicolon, - "expect a ';' after field declarations", - ); - - p.end(m, TreeKind::FieldDecl); -} - fn param_list(p: &mut CParser) { + assert!(p.at(TokenKind::LeftParen)); let m = p.start(); - p.expect_start(TokenKind::LeftParen); + p.expect(TokenKind::LeftParen, "expect '(' to start a parameter list"); while !p.at(TokenKind::RightParen) && !p.eof() { if p.at(TokenKind::Identifier) { parameter(p); @@ -582,9 +541,12 @@ fn param_list(p: &mut CParser) { } fn parameter(p: &mut CParser) { + assert!(p.at(TokenKind::Identifier)); let m = p.start(); - - p.expect_start(TokenKind::Identifier); + p.expect( + TokenKind::Identifier, + "expected an identifier for a parameter name", + ); if p.eat(TokenKind::Colon) { type_expr(p); } @@ -596,9 +558,13 @@ fn parameter(p: &mut CParser) { } fn return_type(p: &mut CParser) { + assert!(p.at(TokenKind::Arrow)); let m = p.start(); - p.expect_start(TokenKind::Arrow); + p.expect( + TokenKind::Arrow, + "function return type starts with an arrow", + ); type_expr(p); p.end(m, TreeKind::ReturnType); @@ -618,9 +584,10 @@ fn type_expr(p: &mut CParser) { } fn type_parameter_list(p: &mut CParser) { + assert!(p.at(TokenKind::Less)); let m = p.start(); - p.expect_start(TokenKind::Less); + p.expect(TokenKind::Less, "expected < to start type parameter list"); while !p.at(TokenKind::Greater) && !p.eof() { if p.at(TokenKind::Identifier) { type_parameter(p); @@ -646,9 +613,10 @@ fn type_parameter(p: &mut CParser) { } fn block(p: &mut CParser) { + assert!(p.at(TokenKind::LeftBrace)); let m = p.start(); - p.expect_start(TokenKind::LeftBrace); + p.expect(TokenKind::LeftBrace, "expect '{' to start a block"); while !p.at(TokenKind::RightBrace) && !p.eof() { statement(p); } @@ -682,9 +650,10 @@ fn statement_if(p: &mut CParser) { } fn statement_let(p: &mut CParser) { + assert!(p.at(TokenKind::Let)); let m = p.start(); - p.expect_start(TokenKind::Let); + p.expect(TokenKind::Let, "expect 'let' to start a let statement"); p.expect(TokenKind::Identifier, "expected a name for the variable"); p.expect(TokenKind::Equal, "expected a '=' after the variable name"); expression(p); @@ -696,9 +665,13 @@ fn statement_let(p: &mut CParser) { } fn statement_return(p: &mut CParser) { + assert!(p.at(TokenKind::Return)); let m = p.start(); - p.expect_start(TokenKind::Return); + p.expect( + TokenKind::Return, + "expect 'return' to start a return statement", + ); expression(p); if !p.at(TokenKind::RightBrace) { p.expect(TokenKind::Semicolon, "expect ';' to end a return statement"); @@ -708,9 +681,10 @@ fn statement_return(p: &mut CParser) { } fn statement_for(p: &mut CParser) { + assert!(p.at(TokenKind::For)); let m = p.start(); - p.expect_start(TokenKind::For); + p.expect(TokenKind::For, "expect a for to start a for loop"); p.expect( TokenKind::Identifier, "expected an identifier for the loop variable", @@ -797,9 +771,13 @@ fn expression_with_power(p: &mut CParser, minimum_power: u8) { } fn argument_list(p: &mut CParser) { + assert!(p.at(TokenKind::LeftParen)); let m = p.start(); - p.expect_start(TokenKind::LeftParen); + p.expect( + TokenKind::LeftParen, + "expect an argument list to start with '('", + ); while !p.at(TokenKind::RightParen) && !p.eof() { argument(p); } @@ -840,8 +818,6 @@ fn prefix_expression(p: &mut CParser) -> MarkClosed { TokenKind::LeftBracket => list_constructor(p), - TokenKind::New => object_constructor(p), - _ => p.advance_with_error("expected an expression"), } } @@ -853,9 +829,10 @@ fn literal(p: &mut CParser) -> MarkClosed { } fn grouping(p: &mut CParser) -> MarkClosed { + assert!(p.at(TokenKind::LeftParen)); let m = p.start(); - p.expect_start(TokenKind::LeftParen); + p.expect(TokenKind::LeftParen, "expected '(' to start grouping"); expression(p); p.expect(TokenKind::RightParen, "unmatched parentheses in expression"); @@ -872,9 +849,10 @@ fn unary(p: &mut CParser) -> MarkClosed { } fn conditional(p: &mut CParser) -> MarkClosed { + assert!(p.at(TokenKind::If)); let m = p.start(); - p.expect_start(TokenKind::If); + p.expect(TokenKind::If, "expected conditional to start with 'if'"); expression(p); block(p); if p.eat(TokenKind::Else) { @@ -899,9 +877,13 @@ fn identifier(p: &mut CParser) -> MarkClosed { } fn list_constructor(p: &mut CParser) -> MarkClosed { + assert!(p.at(TokenKind::LeftBracket)); let m = p.start(); - p.expect_start(TokenKind::LeftBracket); + p.expect( + TokenKind::LeftBracket, + "expect a list constructor to start with [", + ); while !p.at(TokenKind::RightBracket) && !p.eof() { list_constructor_element(p); } @@ -927,49 +909,6 @@ fn list_constructor_element(p: &mut CParser) { p.end(m, TreeKind::ListConstructorElement); } -fn object_constructor(p: &mut CParser) -> MarkClosed { - let m = p.start(); - - p.expect_start(TokenKind::New); - type_expr(p); - if p.at(TokenKind::LeftBrace) { - field_list(p); - } else { - p.error("expected a '{' to start the field list after the class type"); - } - - p.end(m, TreeKind::NewObjectExpression) -} - -fn field_list(p: &mut CParser) { - let m = p.start(); - - p.expect_start(TokenKind::LeftBrace); - while !p.at(TokenKind::RightBrace) && !p.eof() { - field_value(p); - } - p.expect( - TokenKind::RightBrace, - "expected the field list to end with '}'", - ); - - p.end(m, TreeKind::FieldList); -} - -fn field_value(p: &mut CParser) { - let m = p.start(); - - p.expect(TokenKind::Identifier, "expected a field name"); - if p.eat(TokenKind::Colon) { - expression(p); - } - if !p.at(TokenKind::RightBrace) { - p.expect(TokenKind::Comma, "expect a ',' between fields"); - } - - p.end(m, TreeKind::FieldValue); -} - #[cfg(test)] mod tests { use super::*; diff --git a/fine/src/semantics.rs b/fine/src/semantics.rs index b6af291a..598ebcdc 100644 --- a/fine/src/semantics.rs +++ b/fine/src/semantics.rs @@ -57,17 +57,6 @@ impl fmt::Display for Error { } } -pub struct FieldDecl { - pub name: Rc, - pub field_type: Type, -} - -pub struct ClassDecl { - pub name: Rc, - pub fields: Vec, - pub decl_tree: TreeRef, -} - #[derive(Clone)] pub enum Type { // Signals a type error. If you receive this then you know that an error @@ -102,7 +91,6 @@ pub enum Type { Function(Vec>, Box), List(Box), - Class(Rc), } impl Type { @@ -148,7 +136,6 @@ impl fmt::Display for Type { // TODO: Better names TypeVariable(_) => write!(f, "$_"), List(t) => write!(f, "list<{t}>"), - Class(c) => write!(f, "class {}", c.name), } } } @@ -186,10 +173,6 @@ pub enum Declaration { declaration_type: Type, id: ExternalFunctionId, }, - Class { - declaration_type: Type, - declaration: TreeRef, //? - }, } pub struct Environment { @@ -421,9 +404,7 @@ impl<'a> Semantics<'a> { } pub fn snapshot_errors(&self) -> Vec { - let mut result = (*self.errors.borrow()).clone(); - result.sort_by(|a, b| a.start.0.cmp(&b.start.0)); - result + (*self.errors.borrow()).clone() } pub fn logical_parent(&self, tr: TreeRef) -> Option { @@ -700,16 +681,6 @@ impl<'a> Semantics<'a> { .all(|(a, b)| self.type_compat(a, b)) } - (Type::Class(ca), Type::Class(cb)) => { - // TODO: If we were doing structural comparisons here... - // maybe? MAYBE? - // - // Like if this is directional we can look for field - // subsets { ..:int, ..:int } can be { ..:int } etc. - // - ca.decl_tree == cb.decl_tree - } - // Avoid introducing more errors (Type::Error, _) => true, (_, Type::Error) => true, @@ -765,8 +736,6 @@ impl<'a> Semantics<'a> { TreeKind::ListConstructorElement => self.type_of_list_constructor_element(tree), TreeKind::ListConstructor => self.type_of_list_constructor(t, tree), - TreeKind::NewObjectExpression => self.type_of_new_object_expression(tree), - _ => self.internal_compiler_error(Some(t), "asking for a nonsense type"), }; @@ -896,13 +865,6 @@ impl<'a> Semantics<'a> { ); return Some(Type::Error); } - Declaration::Class { .. } => { - self.report_error_tree_ref( - left_tree, - "cannot assign a new value to a class declaration", - ); - return Some(Type::Error); - } }, None => { self.report_error_tree_ref( @@ -1079,13 +1041,6 @@ impl<'a> Semantics<'a> { fn type_of_call(&self, tree: &Tree) -> Option { assert_eq!(tree.kind, TreeKind::CallExpression); - // TODO: Move the vast majority of error checking out of this - // function: once you know that the 0th tree (the function - // expression) yields a function type, assume the type of the - // call is the type of the function return. Don't bother - // matching argument types &c; do that in an explicit - // check_call_expression function below. - let f_ref = tree.nth_tree(0)?; let f = self.type_of(f_ref); @@ -1196,9 +1151,6 @@ impl<'a> Semantics<'a> { Declaration::ExternFunction { declaration_type, .. } => declaration_type.clone(), - Declaration::Class { - declaration_type, .. - } => declaration_type.clone(), }); } @@ -1259,13 +1211,6 @@ impl<'a> Semantics<'a> { Some(Type::List(Box::new(element_type))) } - fn type_of_new_object_expression(&self, tree: &Tree) -> Option { - assert_eq!(tree.kind, TreeKind::NewObjectExpression); - - // NOTE: Matching fields is done in the check function. - Some(self.type_of(tree.nth_tree(1)?)) - } - fn type_of_list_constructor_element(&self, tree: &Tree) -> Option { assert_eq!(tree.kind, TreeKind::ListConstructorElement); Some(self.type_of(tree.nth_tree(0)?)) @@ -1335,12 +1280,6 @@ impl<'a> Semantics<'a> { } => { eprintln!("{declaration_type:?} (extern {id:?})"); } - Declaration::Class { - declaration_type, - declaration, - } => { - eprintln!("{declaration_type:?} (class {declaration:?})"); - } }; } environment = env.parent.clone(); @@ -1382,13 +1321,10 @@ pub fn check(s: &Semantics) { | TreeKind::GroupingExpression | TreeKind::UnaryExpression | TreeKind::ConditionalExpression + | TreeKind::CallExpression | TreeKind::BinaryExpression => { let _ = s.type_of(t); } - TreeKind::CallExpression => { - let _ = s.type_of(t); - } - TreeKind::ArgumentList => {} TreeKind::Argument => { let _ = s.type_of(t); @@ -1407,12 +1343,6 @@ pub fn check(s: &Semantics) { let _ = s.type_of(t); } TreeKind::ForStatement => check_for_statement(s, t), - - TreeKind::ClassDecl => {} - TreeKind::FieldDecl => {} - TreeKind::FieldList => {} - TreeKind::NewObjectExpression => check_new_object_expression(s, tree), - TreeKind::FieldValue => {} } } } @@ -1496,72 +1426,6 @@ fn check_for_statement(s: &Semantics, t: TreeRef) { let _ = s.environment_of(t); } -// TODO: TEST: Check mutual recursion with function calls -// TODO: TEST: Missing fields -// TODO: TEST: Extra fields -// TODO: TEST: Existing and type mismatch - -fn check_new_object_expression(s: &Semantics, tree: &Tree) { - let Some(type_expression) = tree.nth_tree(1) else { - return; - }; - let Some(field_list) = tree.child_tree_of_kind(s.syntax_tree, TreeKind::FieldList) else { - return; - }; - - let class_type = s.type_of(type_expression); - match &class_type { - Type::Class(c) => { - let mut any_errors = false; - let mut field_bindings = HashMap::new(); - for field in field_list.children_of_kind(s.syntax_tree, TreeKind::FieldValue) { - let f = &s.syntax_tree[field]; - if let Some(name) = f.nth_token(0) { - let field_type = s.type_of(field); - field_bindings.insert(name.as_str(), (field, field_type)); - } else { - any_errors = true; - } - } - - // Check individual bindings... - for f in c.fields.iter() { - if let Some((field_tree, expr_type)) = field_bindings.get(&*f.name) { - if !s.type_compat(&f.field_type, expr_type) { - s.report_error_tree_ref( - *field_tree, - format!( - "field {} has is of type {}, but this expression generates a {}", - f.name, f.field_type, expr_type, - ), - ); - } - field_bindings.remove(&*f.name); - } else if !any_errors { - s.report_error_tree( - tree, - format!("missing an initializer for field {}", f.name), - ); - } - } - - if !any_errors { - for (n, (field_tree, _)) in field_bindings.iter() { - s.report_error_tree_ref( - *field_tree, - format!("{} does not have a field named {}", class_type, n), - ); - } - } - } - Type::Error => (), - ct => s.report_error_tree_ref( - type_expression, - format!("expected this to be a class type, but it is {ct}"), - ), - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/fine/src/tokens.rs b/fine/src/tokens.rs index de00ecc5..707b65d9 100644 --- a/fine/src/tokens.rs +++ b/fine/src/tokens.rs @@ -49,7 +49,6 @@ pub enum TokenKind { Import, In, Let, - New, Or, Return, Select, @@ -303,11 +302,6 @@ impl<'a> Tokens<'a> { return TokenKind::Let; } } - 'n' => { - if ident == "new" { - return TokenKind::New; - } - } 'o' => { if ident == "or" { return TokenKind::Or; @@ -579,7 +573,7 @@ mod tests { test_tokens!( more_keywords, - "fun if import let return select this true while truewhile new", + "fun if import let return select this true while truewhile", (0, Fun, "fun"), (4, If, "if"), (7, Import, "import"), @@ -589,8 +583,7 @@ mod tests { (32, This, "this"), (37, True, "true"), (42, While, "while"), - (48, Identifier, "truewhile"), - (58, New, "new") + (48, Identifier, "truewhile") ); test_tokens!( diff --git a/fine/src/vm.rs b/fine/src/vm.rs index 18d68990..68d05a2c 100644 --- a/fine/src/vm.rs +++ b/fine/src/vm.rs @@ -39,12 +39,6 @@ pub struct VMError { type Result = std::result::Result; -#[derive(Clone, Debug)] -pub struct Object { - name: Rc, - values: Box<[StackValue]>, -} - #[derive(Clone, Debug)] pub enum StackValue { Nothing, @@ -53,7 +47,6 @@ pub enum StackValue { String(Rc), Function(Rc), ExternFunction(usize), - Object(Rc), } enum FuncValue { @@ -137,10 +130,6 @@ impl Frame { self.push_value(StackValue::ExternFunction(v)); } - fn push_object(&mut self, v: Rc) { - self.push_value(StackValue::Object(v)); - } - fn get_argument(&self, i: usize) -> Result { self.args .get(i) @@ -395,21 +384,6 @@ fn eval_one( let y = f.pop_string()?; f.push_bool(x == y); } - - Instruction::NewObject(slots) => { - let name = f.pop_string()?; - let mut values = Vec::with_capacity(slots); - for _ in 0..slots { - values.push(f.pop_value()?); - } - - let object = Object { - name, - values: values.into(), - }; - - f.push_object(object.into()); - } } Ok(Flow::Continue) diff --git a/fine/tests/expression/class.fine b/fine/tests/expression/class.fine deleted file mode 100644 index 9cdbae8d..00000000 --- a/fine/tests/expression/class.fine +++ /dev/null @@ -1,13 +0,0 @@ -class Point { - x: f64; - y: f64; -} - -fun test() -> f64 { - let pt = new Point { x: 7, y: 23 }; - let z = pt.x; - z -} - -// @ignore -// @no-errors diff --git a/fine/tests/expression/errors/class_duplicate_fields.fine b/fine/tests/expression/errors/class_duplicate_fields.fine deleted file mode 100644 index 396edc01..00000000 --- a/fine/tests/expression/errors/class_duplicate_fields.fine +++ /dev/null @@ -1,8 +0,0 @@ -class Foo { - x: f64; - x: f64; -} - -// @ignore -// @expect-errors: -// asdfadsf diff --git a/fine/tests/expression/errors/duplicate_arguments.fine b/fine/tests/expression/errors/duplicate_arguments.fine deleted file mode 100644 index 7dfb6127..00000000 --- a/fine/tests/expression/errors/duplicate_arguments.fine +++ /dev/null @@ -1,5 +0,0 @@ -fun something(x: f64, x: f64) {} - -// @ignore -// @expect-errors: -// asdfadsf diff --git a/fine/tests/expression/lists.fine b/fine/tests/expression/lists.fine index 2630735b..3c9c577b 100644 --- a/fine/tests/expression/lists.fine +++ b/fine/tests/expression/lists.fine @@ -1,14 +1,10 @@ fun sum(x: list) -> f64 { - let result = 0; - for v in x { - result = result + v; - } - result + 75 // lol } -fun test() -> f64 { +fun test() { let val = [1, 2, 3]; - sum(val) + sum(val); } // @no-errors