From 619dac36fecd955b21a13d96f5e61ad77944f7cd Mon Sep 17 00:00:00 2001 From: Gavrilikhin Daniil Date: Thu, 7 Mar 2024 10:42:26 +0800 Subject: [PATCH 1/5] Impl Ranged for AST --- src/ast/declarations/function.rs | 16 +++++++++- src/ast/declarations/mod.rs | 16 +++++++++- src/ast/declarations/trait.rs | 20 ++++++++++-- src/ast/declarations/types.rs | 25 ++++++++++++++- src/ast/declarations/variable.rs | 12 +++++++- src/ast/statements/assignment.rs | 12 +++++++- src/ast/statements/if.rs | 53 ++++++++++++++++++++++++++++++-- src/ast/statements/loop.rs | 14 ++++++++- src/ast/statements/mod.rs | 20 +++++++++++- src/ast/statements/while.rs | 20 ++++++++++-- 10 files changed, 194 insertions(+), 14 deletions(-) diff --git a/src/ast/declarations/function.rs b/src/ast/declarations/function.rs index 2f6883e2..fe005ead 100644 --- a/src/ast/declarations/function.rs +++ b/src/ast/declarations/function.rs @@ -6,7 +6,8 @@ use derive_more::From; use crate::{ ast::{Annotation, Expression, Statement, TypeReference}, syntax::{ - error::ParseError, Context, Identifier, Keyword, Lexer, OperatorKind, Parse, Ranged, StartsHere, StringWithOffset, Token + error::ParseError, Context, Identifier, Keyword, Lexer, OperatorKind, Parse, Ranged, + StartsHere, StringWithOffset, Token, }, }; @@ -163,6 +164,19 @@ pub struct FunctionDeclaration { pub annotations: Vec, } +impl Ranged for FunctionDeclaration { + fn start(&self) -> usize { + self.keyword.start() + } + + fn end(&self) -> usize { + self.body + .last() + // FIXME: respect return_type, name_parts, generic_parameters + .map_or_else(|| self.keyword.end(), |s| s.end()) + } +} + impl StartsHere for FunctionDeclaration { /// Check that function declaration may start at current lexer position fn starts_here(context: &mut Context) -> bool { diff --git a/src/ast/declarations/mod.rs b/src/ast/declarations/mod.rs index 284ed4e6..89e30eca 100644 --- a/src/ast/declarations/mod.rs +++ b/src/ast/declarations/mod.rs @@ -1,4 +1,6 @@ mod function; +use std::ops::Range; + pub use function::*; mod types; @@ -15,7 +17,7 @@ use ast_derive::AST; use crate::syntax::{ error::{MissingDeclaration, ParseError}, - Context, Lexer, Parse, StartsHere, Token, + Context, Lexer, Parse, Ranged, StartsHere, Token, }; use derive_more::From; @@ -29,6 +31,18 @@ pub enum Declaration { Trait(TraitDeclaration), } +impl Ranged for Declaration { + fn range(&self) -> Range { + use Declaration::*; + match self { + Variable(s) => s.range(), + Type(s) => s.range(), + Function(s) => s.range(), + Trait(s) => s.range(), + } + } +} + impl StartsHere for Declaration { /// Check literal may start at current lexer position fn starts_here(context: &mut Context) -> bool { diff --git a/src/ast/declarations/trait.rs b/src/ast/declarations/trait.rs index 39139c55..66c62559 100644 --- a/src/ast/declarations/trait.rs +++ b/src/ast/declarations/trait.rs @@ -2,7 +2,7 @@ extern crate ast_derive; use ast_derive::AST; use crate::syntax::{ - error::ParseError, Context, Identifier, Keyword, Lexer, Parse, StartsHere, Token + error::ParseError, Context, Identifier, Keyword, Lexer, Parse, Ranged, StartsHere, Token, }; use super::FunctionDeclaration; @@ -18,6 +18,18 @@ pub struct TraitDeclaration { pub functions: Vec, } +impl Ranged for TraitDeclaration { + fn start(&self) -> usize { + self.keyword.start() + } + + fn end(&self) -> usize { + self.functions + .last() + .map_or_else(|| self.name.end(), |s| s.end()) + } +} + impl StartsHere for TraitDeclaration { /// Check that type declaration may start at current lexer position fn starts_here(context: &mut Context) -> bool { @@ -38,6 +50,10 @@ impl Parse for TraitDeclaration { let functions = context.parse_block(FunctionDeclaration::parse)?; - Ok(TraitDeclaration { keyword, name, functions }) + Ok(TraitDeclaration { + keyword, + name, + functions, + }) } } diff --git a/src/ast/declarations/types.rs b/src/ast/declarations/types.rs index 82d6b7c2..f440ccc1 100644 --- a/src/ast/declarations/types.rs +++ b/src/ast/declarations/types.rs @@ -4,7 +4,7 @@ use ast_derive::AST; use crate::{ ast::{Annotation, TypeReference}, syntax::{ - error::ParseError, Context, Identifier, Keyword, Lexer, Parse, StartsHere, Token + error::ParseError, Context, Identifier, Keyword, Lexer, Parse, Ranged, StartsHere, Token, }, }; @@ -17,6 +17,16 @@ pub struct Member { pub ty: TypeReference, } +impl Ranged for Member { + fn start(&self) -> usize { + self.name.start() + } + + fn end(&self) -> usize { + self.ty.end() + } +} + /// Parse single or multiple members, if they are separated by comma pub fn parse_members(context: &mut Context) -> Result, ParseError> { let names = context.parse_comma_separated(|context| context.consume_id()); @@ -77,6 +87,19 @@ pub struct TypeDeclaration { pub members: Vec, } +impl Ranged for TypeDeclaration { + fn start(&self) -> usize { + self.keyword.start() + } + + fn end(&self) -> usize { + self.members + .last() + // FIXME: respect generic parameters + .map_or_else(|| self.name.end(), |s| s.end()) + } +} + impl StartsHere for TypeDeclaration { /// Check that type declaration may start at current lexer position fn starts_here(context: &mut Context) -> bool { diff --git a/src/ast/declarations/variable.rs b/src/ast/declarations/variable.rs index 8c6c7342..ca9c0e5c 100644 --- a/src/ast/declarations/variable.rs +++ b/src/ast/declarations/variable.rs @@ -4,7 +4,7 @@ use ast_derive::AST; use crate::ast::{Expression, TypeReference}; use crate::mutability::{Mutability, Mutable}; use crate::syntax::error::{MissingVariableName, ParseError}; -use crate::syntax::{Context, Identifier, Keyword, Lexer, Parse, StartsHere, Token}; +use crate::syntax::{Context, Identifier, Keyword, Lexer, Parse, Ranged, StartsHere, Token}; /// Declaration of the variable #[derive(Debug, PartialEq, Eq, AST, Clone)] @@ -22,6 +22,16 @@ pub struct VariableDeclaration { pub mutability: Mutability, } +impl Ranged for VariableDeclaration { + fn start(&self) -> usize { + self.keyword.start() + } + + fn end(&self) -> usize { + self.initializer.end() + } +} + impl Mutable for VariableDeclaration { fn is_mutable(&self) -> bool { self.mutability.is_mutable() diff --git a/src/ast/statements/assignment.rs b/src/ast/statements/assignment.rs index 95803875..8f80b26f 100644 --- a/src/ast/statements/assignment.rs +++ b/src/ast/statements/assignment.rs @@ -3,7 +3,7 @@ use ast_derive::AST; use crate::ast::Expression; use crate::syntax::{error::ParseError, Lexer, Parse, Token}; -use crate::syntax::{Context, StartsHere}; +use crate::syntax::{Context, Ranged, StartsHere}; /// AST for assignment #[derive(Debug, PartialEq, Eq, AST, Clone)] @@ -14,6 +14,16 @@ pub struct Assignment { pub value: Expression, } +impl Ranged for Assignment { + fn start(&self) -> usize { + self.target.start() + } + + fn end(&self) -> usize { + self.value.end() + } +} + impl StartsHere for Assignment { /// Check that assignment may start at current lexer position fn starts_here(context: &mut Context) -> bool { diff --git a/src/ast/statements/if.rs b/src/ast/statements/if.rs index 8ea5a1fa..c4b3deaa 100644 --- a/src/ast/statements/if.rs +++ b/src/ast/statements/if.rs @@ -3,7 +3,7 @@ use ast_derive::AST; use crate::ast::Expression; use crate::syntax::{error::ParseError, Lexer, Parse, Token}; -use crate::syntax::{Context, Keyword, StartsHere}; +use crate::syntax::{Context, Keyword, Ranged, StartsHere}; use super::Statement; @@ -19,6 +19,18 @@ pub struct ElseIf { pub body: Vec, } +impl Ranged for ElseIf { + fn start(&self) -> usize { + self.else_keyword.start() + } + + fn end(&self) -> usize { + self.body + .last() + .map_or_else(|| self.condition.end(), |s| s.end()) + } +} + /// AST for else block #[derive(Debug, PartialEq, Eq, Clone)] pub struct Else { @@ -28,6 +40,18 @@ pub struct Else { pub body: Vec, } +impl Ranged for Else { + fn start(&self) -> usize { + self.keyword.start() + } + + fn end(&self) -> usize { + self.body + .last() + .map_or_else(|| self.keyword.end(), |s| s.end()) + } +} + /// AST for if-statement #[derive(Debug, PartialEq, Eq, AST, Clone)] pub struct If { @@ -43,6 +67,24 @@ pub struct If { pub else_block: Option, } +impl Ranged for If { + fn start(&self) -> usize { + self.keyword.start() + } + + fn end(&self) -> usize { + if let Some(else_block) = &self.else_block { + else_block.end() + } else if let Some(else_if) = self.else_ifs.last() { + else_if.end() + } else { + self.body + .last() + .map_or_else(|| self.condition.end(), |s| s.end()) + } + } +} + impl StartsHere for If { /// Check that assignment may start at current lexer position fn starts_here(context: &mut Context) -> bool { @@ -71,12 +113,17 @@ impl Parse for If { context.lexer.consume(Token::Colon)?; let body = context.parse_block(Statement::parse)?; - else_ifs.push(ElseIf { else_keyword, if_keyword, condition, body }); + else_ifs.push(ElseIf { + else_keyword, + if_keyword, + condition, + body, + }); } else { context.lexer.consume(Token::Colon)?; else_block = Some(Else { keyword: else_keyword, - body: context.parse_block(Statement::parse)? + body: context.parse_block(Statement::parse)?, }); break; } diff --git a/src/ast/statements/loop.rs b/src/ast/statements/loop.rs index a4fced1c..001fef44 100644 --- a/src/ast/statements/loop.rs +++ b/src/ast/statements/loop.rs @@ -4,7 +4,7 @@ use ast_derive::AST; use crate::ast::Statement; use crate::syntax::{error::ParseError, Lexer, Parse, Token}; -use crate::syntax::{Context, Keyword, StartsHere}; +use crate::syntax::{Context, Keyword, Ranged, StartsHere}; /// AST for infinite loop #[derive(Debug, PartialEq, Eq, AST, Clone)] @@ -14,6 +14,18 @@ pub struct Loop { pub body: Vec, } +impl Ranged for Loop { + fn start(&self) -> usize { + self.keyword.start() + } + + fn end(&self) -> usize { + self.body + .last() + .map_or_else(|| self.keyword.end(), |s| s.end()) + } +} + impl StartsHere for Loop { /// Check that loop starts at current lexer position fn starts_here(context: &mut Context) -> bool { diff --git a/src/ast/statements/mod.rs b/src/ast/statements/mod.rs index 35ef854e..ffe9869d 100644 --- a/src/ast/statements/mod.rs +++ b/src/ast/statements/mod.rs @@ -1,4 +1,6 @@ mod assignment; +use std::ops::Range; + pub use assignment::*; mod ret; @@ -22,7 +24,7 @@ use ast_derive::AST; use crate::ast::{Declaration, Expression}; use crate::syntax::error::MissingStatement; use crate::syntax::{error::ParseError, Lexer, Parse, Token}; -use crate::syntax::{Context, StartsHere}; +use crate::syntax::{Context, Ranged, StartsHere}; use derive_more::From; @@ -41,6 +43,22 @@ pub enum Statement { Use(Use), } +impl Ranged for Statement { + fn range(&self) -> Range { + use Statement::*; + match self { + Declaration(s) => s.range(), + Expression(s) => s.range(), + Assignment(s) => s.range(), + Return(s) => s.range(), + If(s) => s.range(), + Loop(s) => s.range(), + While(s) => s.range(), + Use(s) => s.range(), + } + } +} + impl StartsHere for Statement { /// Check that statement may start at current lexer position fn starts_here(context: &mut Context) -> bool { diff --git a/src/ast/statements/while.rs b/src/ast/statements/while.rs index d0a6ddc0..1ac28369 100644 --- a/src/ast/statements/while.rs +++ b/src/ast/statements/while.rs @@ -4,7 +4,7 @@ use ast_derive::AST; use crate::ast::{Expression, Statement}; use crate::syntax::{error::ParseError, Lexer, Parse, Token}; -use crate::syntax::{Context, Keyword, StartsHere}; +use crate::syntax::{Context, Keyword, Ranged, StartsHere}; /// AST for while loop #[derive(Debug, PartialEq, Eq, AST, Clone)] @@ -17,6 +17,18 @@ pub struct While { pub body: Vec, } +impl Ranged for While { + fn start(&self) -> usize { + self.keyword.start() + } + + fn end(&self) -> usize { + self.body + .last() + .map_or_else(|| self.condition.end(), |s| s.end()) + } +} + impl StartsHere for While { /// Check that loop starts at current lexer position fn starts_here(context: &mut Context) -> bool { @@ -37,6 +49,10 @@ impl Parse for While { let body = context.parse_block(Statement::parse)?; - Ok(While { keyword, condition, body }) + Ok(While { + keyword, + condition, + body, + }) } } From b25e3a3536a38f8d4d8a26e2bd1986b1cb2c2b79 Mon Sep 17 00:00:00 2001 From: Gavrilikhin Daniil Date: Thu, 7 Mar 2024 10:42:35 +0800 Subject: [PATCH 2/5] Fix defining predeclared --- src/semantics/to_hir.rs | 64 ++++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 17 deletions(-) diff --git a/src/semantics/to_hir.rs b/src/semantics/to_hir.rs index 6071b93a..ef568c85 100644 --- a/src/semantics/to_hir.rs +++ b/src/semantics/to_hir.rs @@ -816,28 +816,45 @@ impl ToHIR for ast::Module { let mut errors = Vec::new(); - macro_rules! define { + // Import things first + self.statements + .iter() + .filter(|s| matches!(s, ast::Statement::Use(_))) + .for_each(|stmt: &S| { + let res = stmt.to_hir(context); + match res { + Ok(mut stmt) => { + stmt.monomorphize(context); + context.module_mut().statements.push(stmt) + } + Err(err) => errors.push(err), + } + }); + + let mut decls = HashMap::new(); + + macro_rules! declare { () => { |stmt: &S| { - let res = stmt.to_hir(context); + let decl: &D = match stmt { + S::Declaration(d) => d, + _ => return, + }; + + let res = decl.declare(context); match res { - Ok(mut stmt) => { - stmt.monomorphize(context); - context.module_mut().statements.push(stmt) + Ok(decl) => { + decls.insert(stmt.start(), decl); + } + Err(err) => { + errors.push(err); } - Err(err) => errors.push(err), } } }; } - // Import things first - self.statements - .iter() - .filter(|s| matches!(s, ast::Statement::Use(_))) - .for_each(define!()); - - macro_rules! declare { + macro_rules! define { () => { |stmt: &S| { let decl: &D = match stmt { @@ -845,9 +862,13 @@ impl ToHIR for ast::Module { _ => return, }; - let res = decl.declare(context); - if let Err(err) = res { - errors.push(err); + let res = decl.define(decls.remove(&decl.start()).unwrap(), context); + match res { + Ok(mut stmt) => { + stmt.monomorphize(context); + context.module_mut().statements.push(stmt.into()) + } + Err(err) => errors.push(err), } } }; @@ -887,7 +908,16 @@ impl ToHIR for ast::Module { self.statements .iter() .filter(|s| !matches!(s, S::Use(_) | S::Declaration(_))) - .for_each(define!()); + .for_each(|stmt: &S| { + let res = stmt.to_hir(context); + match res { + Ok(mut stmt) => { + stmt.monomorphize(context); + context.module_mut().statements.push(stmt) + } + Err(err) => errors.push(err), + } + }); if !errors.is_empty() { return Err(errors.into()); From 7b4be8c2e05af4a7ac6ad5581a9c7ee9c0c53225 Mon Sep 17 00:00:00 2001 From: Gavrilikhin Daniil Date: Thu, 7 Mar 2024 10:43:15 +0800 Subject: [PATCH 3/5] Fix reference_mut --- src/semantics/tests/reference_mut/reference_mut.ppl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/semantics/tests/reference_mut/reference_mut.ppl b/src/semantics/tests/reference_mut/reference_mut.ppl index ef8592b9..661b71d3 100644 --- a/src/semantics/tests/reference_mut/reference_mut.ppl +++ b/src/semantics/tests/reference_mut/reference_mut.ppl @@ -1,6 +1,6 @@ let mut x = 1 let y = reference to mutable x println y -// y = 2 -// println y -// println x +y = 2 +println y +println x From e83c5bfa64d17b7ec9de79c77d7529134bcd8ff4 Mon Sep 17 00:00:00 2001 From: Gavrilikhin Daniil Date: Thu, 7 Mar 2024 10:45:43 +0800 Subject: [PATCH 4/5] Fix candidate_not_viable --- .../tests/candidate_not_viable/stderr.log | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/semantics/tests/candidate_not_viable/stderr.log b/src/semantics/tests/candidate_not_viable/stderr.log index 63f5ddef..871b3721 100644 --- a/src/semantics/tests/candidate_not_viable/stderr.log +++ b/src/semantics/tests/candidate_not_viable/stderr.log @@ -12,12 +12,12 @@ Error: semantics::no_function Advice: ☞ candidate is not viable: expected `Integer` type, got `Rational` Error: × Integer - ╭─[ppl.ppl:87:5] - 86 │ @mangle_as("integer_plus_integer") - 87 │ fn <:Integer> + <:Integer> -> Integer + ╭─[ppl.ppl:90:5] + 89 │ @mangle_as("integer_plus_integer") + 90 │ fn <:Integer> + <:Integer> -> Integer · ▲ · ╰── this has `Integer` type - 88 │ + 91 │ ╰──── Error: × Rational ╭─[candidate_not_viable.ppl:1:1] @@ -28,12 +28,12 @@ Error: × Rational Advice: ☞ candidate is not viable: expected `Rational` type, got `Integer` Error: × Rational - ╭─[ppl.ppl:145:19] - 144 │ @mangle_as("rational_plus_rational") - 145 │ fn <:Rational> + <:Rational> -> Rational + ╭─[ppl.ppl:151:19] + 150 │ @mangle_as("rational_plus_rational") + 151 │ fn <:Rational> + <:Rational> -> Rational · ▲ · ╰── this has `Rational` type - 146 │ + 152 │ ╰──── Error: × Integer ╭─[candidate_not_viable.ppl:1:7] @@ -44,12 +44,12 @@ Error: × Integer Advice: ☞ candidate is not viable: expected `String` type, got `Rational` Error: × String - ╭─[ppl.ppl:172:5] - 171 │ @mangle_as("string_plus_string") - 172 │ fn <:String> + <:String> -> String + ╭─[ppl.ppl:181:5] + 180 │ @mangle_as("string_plus_string") + 181 │ fn <:String> + <:String> -> String · ▲ · ╰── this has `String` type - 173 │ + 182 │ ╰──── Error: × Rational ╭─[candidate_not_viable.ppl:1:1] @@ -60,12 +60,12 @@ Error: × Rational Advice: ☞ candidate is not viable: expected `MemoryAddress` type, got `Rational` Error: × MemoryAddress - ╭─[ppl.ppl:247:5] - 246 │ /// Get another memory address by adding offset to this one - 247 │ fn + -> MemoryAddress: + ╭─[ppl.ppl:256:5] + 255 │ /// Get another memory address by adding offset to this one + 256 │ fn + -> MemoryAddress: · ───┬─── · ╰── this has `MemoryAddress` type - 248 │ let value = address.value + offset + 257 │ let value = address.value + offset ╰──── Error: × Rational ╭─[candidate_not_viable.ppl:1:1] @@ -76,12 +76,12 @@ Error: × Rational Advice: ☞ candidate is not viable: expected `I32` type, got `Rational` Error: × I32 - ╭─[ppl.ppl:365:5] - 364 │ @mangle_as("i32_plus_i32") - 365 │ fn <:I32> + <:I32> -> I32 + ╭─[ppl.ppl:374:5] + 373 │ @mangle_as("i32_plus_i32") + 374 │ fn <:I32> + <:I32> -> I32 · ▲ · ╰── this has `I32` type - 366 │ + 375 │ ╰──── Error: × Rational ╭─[candidate_not_viable.ppl:1:1] From 53e41b67a44826073e6e169426e5b74f2df30d32 Mon Sep 17 00:00:00 2001 From: Gavrilikhin Daniil Date: Thu, 7 Mar 2024 10:46:25 +0800 Subject: [PATCH 5/5] Fix memory test --- src/semantics/tests/memory/memory.ppl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/semantics/tests/memory/memory.ppl b/src/semantics/tests/memory/memory.ppl index b9a1b287..61fd11ea 100644 --- a/src/semantics/tests/memory/memory.ppl +++ b/src/semantics/tests/memory/memory.ppl @@ -1,5 +1,6 @@ let address = allocate 1 Integer let x = Integer at address +x = 0 println x x = 1 println x \ No newline at end of file