diff --git a/schala-lang/language/src/ast/mod.rs b/schala-lang/language/src/ast/mod.rs index c48c9a6..fe06699 100644 --- a/schala-lang/language/src/ast/mod.rs +++ b/schala-lang/language/src/ast/mod.rs @@ -1,18 +1,22 @@ #![allow(clippy::upper_case_acronyms)] #![allow(clippy::enum_variant_names)] -use std::rc::Rc; -use std::convert::{AsRef, From}; +use std::{ + convert::{AsRef, From}, + rc::Rc, +}; -mod visitor; mod operators; +mod visitor; -pub use operators::{PrefixOp, BinOp}; +pub use operators::{BinOp, PrefixOp}; pub use visitor::*; -use crate::derivative::Derivative; -use crate::tokenizing::Location; -use crate::identifier::{Id, define_id_kind}; +use crate::{ + derivative::Derivative, + identifier::{define_id_kind, Id}, + tokenizing::Location, +}; define_id_kind!(ASTItem); @@ -29,32 +33,32 @@ pub type ItemId = Id; #[derive(Derivative, Debug)] #[derivative(PartialEq)] pub struct AST { - #[derivative(PartialEq="ignore")] - pub id: ItemId, - pub statements: Block, + #[derivative(PartialEq = "ignore")] + pub id: ItemId, + pub statements: Block, } #[derive(Derivative, Debug, Clone)] #[derivative(PartialEq)] pub struct Statement { - #[derivative(PartialEq="ignore")] - pub id: ItemId, - #[derivative(PartialEq="ignore")] - pub location: Location, - pub kind: StatementKind, + #[derivative(PartialEq = "ignore")] + pub id: ItemId, + #[derivative(PartialEq = "ignore")] + pub location: Location, + pub kind: StatementKind, } #[derive(Debug, PartialEq, Clone)] pub enum StatementKind { - Expression(Expression), - Declaration(Declaration), - Import(ImportSpecifier), - Module(ModuleSpecifier), + Expression(Expression), + Declaration(Declaration), + Import(ImportSpecifier), + Module(ModuleSpecifier), } #[derive(Debug, Clone, PartialEq, Default)] pub struct Block { - pub statements: Vec + pub statements: Vec, } impl From> for Block { @@ -80,59 +84,37 @@ pub type ParamName = Rc; #[derive(Debug, Derivative, Clone)] #[derivative(PartialEq)] pub struct QualifiedName { - #[derivative(PartialEq="ignore")] - pub id: ItemId, - pub components: Vec>, + #[derivative(PartialEq = "ignore")] + pub id: ItemId, + pub components: Vec>, } #[derive(Debug, PartialEq, Clone)] pub struct FormalParam { - pub name: ParamName, - pub default: Option, - pub anno: Option + pub name: ParamName, + pub default: Option, + pub anno: Option, } #[derive(Debug, PartialEq, Clone)] pub enum Declaration { - FuncSig(Signature), - FuncDecl(Signature, Block), - TypeDecl { - name: TypeSingletonName, - body: TypeBody, - mutable: bool - }, - //TODO this needs to be more sophisticated - TypeAlias { - alias: Rc, - original: Rc, - }, - Binding { - name: Rc, - constant: bool, - type_anno: Option, - expr: Expression, - }, - Impl { - type_name: TypeIdentifier, - interface_name: Option, - block: Vec, - }, - Interface { - name: Rc, - signatures: Vec - }, - Annotation { - name: Rc, - arguments: Vec - } + FuncSig(Signature), + FuncDecl(Signature, Block), + TypeDecl { name: TypeSingletonName, body: TypeBody, mutable: bool }, + //TODO this needs to be more sophisticated + TypeAlias { alias: Rc, original: Rc }, + Binding { name: Rc, constant: bool, type_anno: Option, expr: Expression }, + Impl { type_name: TypeIdentifier, interface_name: Option, block: Vec }, + Interface { name: Rc, signatures: Vec }, + Annotation { name: Rc, arguments: Vec }, } #[derive(Debug, PartialEq, Clone)] pub struct Signature { - pub name: Rc, - pub operator: bool, - pub params: Vec, - pub type_anno: Option, + pub name: Rc, + pub operator: bool, + pub params: Vec, + pub type_anno: Option, } #[derive(Debug, PartialEq, Clone)] @@ -141,184 +123,147 @@ pub struct TypeBody(pub Vec); #[derive(Debug, Derivative, Clone)] #[derivative(PartialEq)] pub struct Variant { - #[derivative(PartialEq="ignore")] + #[derivative(PartialEq = "ignore")] pub id: ItemId, pub name: Rc, pub kind: VariantKind, - } +} #[derive(Debug, PartialEq, Clone)] pub enum VariantKind { UnitStruct, TupleStruct(Vec), Record(Vec<(Rc, TypeIdentifier)>), - } +} #[derive(Debug, Derivative, Clone)] #[derivative(PartialEq)] pub struct Expression { - #[derivative(PartialEq="ignore")] - pub id: ItemId, - pub kind: ExpressionKind, - pub type_anno: Option + #[derivative(PartialEq = "ignore")] + pub id: ItemId, + pub kind: ExpressionKind, + pub type_anno: Option, } impl Expression { - pub fn new(id: ItemId, kind: ExpressionKind) -> Expression { - Expression { id, kind, type_anno: None } - } + pub fn new(id: ItemId, kind: ExpressionKind) -> Expression { + Expression { id, kind, type_anno: None } + } - #[cfg(test)] - pub fn with_anno(id: ItemId, kind: ExpressionKind, type_anno: TypeIdentifier) -> Expression { - Expression { id, kind, type_anno: Some(type_anno) } - } + #[cfg(test)] + pub fn with_anno(id: ItemId, kind: ExpressionKind, type_anno: TypeIdentifier) -> Expression { + Expression { id, kind, type_anno: Some(type_anno) } + } } #[derive(Debug, PartialEq, Clone)] pub enum TypeIdentifier { - Tuple(Vec), - Singleton(TypeSingletonName) + Tuple(Vec), + Singleton(TypeSingletonName), } #[derive(Debug, PartialEq, Clone)] pub struct TypeSingletonName { - pub name: Rc, - pub params: Vec, + pub name: Rc, + pub params: Vec, } #[derive(Debug, PartialEq, Clone)] pub enum ExpressionKind { - NatLiteral(u64), - FloatLiteral(f64), - StringLiteral(Rc), - BoolLiteral(bool), - BinExp(BinOp, Box, Box), - PrefixExp(PrefixOp, Box), - TupleLiteral(Vec), - Value(QualifiedName), - NamedStruct { - name: QualifiedName, - fields: Vec<(Rc, Expression)>, - }, - Call { - f: Box, - arguments: Vec, - }, - Index { - indexee: Box, - indexers: Vec, - }, - IfExpression { - discriminator: Option>, - body: Box, - }, - WhileExpression { - condition: Option>, - body: Block, - }, - ForExpression { - enumerators: Vec, - body: Box, - }, - Lambda { - params: Vec, - type_anno: Option, - body: Block, - }, - ListLiteral(Vec), + NatLiteral(u64), + FloatLiteral(f64), + StringLiteral(Rc), + BoolLiteral(bool), + BinExp(BinOp, Box, Box), + PrefixExp(PrefixOp, Box), + TupleLiteral(Vec), + Value(QualifiedName), + NamedStruct { name: QualifiedName, fields: Vec<(Rc, Expression)> }, + Call { f: Box, arguments: Vec }, + Index { indexee: Box, indexers: Vec }, + IfExpression { discriminator: Option>, body: Box }, + WhileExpression { condition: Option>, body: Block }, + ForExpression { enumerators: Vec, body: Box }, + Lambda { params: Vec, type_anno: Option, body: Block }, + ListLiteral(Vec), } #[derive(Debug, PartialEq, Clone)] pub enum InvocationArgument { - Positional(Expression), - Keyword { - name: Rc, - expr: Expression, - }, - Ignored + Positional(Expression), + Keyword { name: Rc, expr: Expression }, + Ignored, } #[derive(Debug, PartialEq, Clone)] pub enum IfExpressionBody { - SimpleConditional { - then_case: Block, - else_case: Option - }, - SimplePatternMatch { - pattern: Pattern, - then_case: Block, - else_case: Option - }, - CondList(Vec) + SimpleConditional { then_case: Block, else_case: Option }, + SimplePatternMatch { pattern: Pattern, then_case: Block, else_case: Option }, + CondList(Vec), } #[derive(Debug, PartialEq, Clone)] pub struct ConditionArm { - pub condition: Condition, - pub guard: Option, - pub body: Block, + pub condition: Condition, + pub guard: Option, + pub body: Block, } #[derive(Debug, PartialEq, Clone)] pub enum Condition { - Pattern(Pattern), - TruncatedOp(BinOp, Expression), - Expression(Expression), - Else, + Pattern(Pattern), + TruncatedOp(BinOp, Expression), + Expression(Expression), + Else, } #[derive(Debug, PartialEq, Clone)] pub enum Pattern { - Ignored, - TuplePattern(Vec), - Literal(PatternLiteral), - TupleStruct(QualifiedName, Vec), - Record(QualifiedName, Vec<(Rc, Pattern)>), - VarOrName(QualifiedName), + Ignored, + TuplePattern(Vec), + Literal(PatternLiteral), + TupleStruct(QualifiedName, Vec), + Record(QualifiedName, Vec<(Rc, Pattern)>), + VarOrName(QualifiedName), } #[derive(Debug, PartialEq, Clone)] pub enum PatternLiteral { - NumPattern { - neg: bool, - num: ExpressionKind, - }, - StringPattern(Rc), - BoolPattern(bool), + NumPattern { neg: bool, num: ExpressionKind }, + StringPattern(Rc), + BoolPattern(bool), } #[derive(Debug, PartialEq, Clone)] pub struct Enumerator { - pub id: Rc, - pub generator: Expression, + pub id: Rc, + pub generator: Expression, } #[derive(Debug, PartialEq, Clone)] pub enum ForBody { - MonadicReturn(Expression), - StatementBlock(Block), + MonadicReturn(Expression), + StatementBlock(Block), } #[derive(Debug, Derivative, Clone)] #[derivative(PartialEq)] pub struct ImportSpecifier { - #[derivative(PartialEq="ignore")] - pub id: ItemId, - pub path_components: Vec>, - pub imported_names: ImportedNames + #[derivative(PartialEq = "ignore")] + pub id: ItemId, + pub path_components: Vec>, + pub imported_names: ImportedNames, } #[derive(Debug, PartialEq, Clone)] pub enum ImportedNames { - All, - LastOfPath, - List(Vec>) + All, + LastOfPath, + List(Vec>), } - #[derive(Debug, PartialEq, Clone)] pub struct ModuleSpecifier { - pub name: Rc, - pub contents: Block, + pub name: Rc, + pub contents: Block, } - diff --git a/schala-lang/language/src/ast/operators.rs b/schala-lang/language/src/ast/operators.rs index 5e11830..c7cbf9d 100644 --- a/schala-lang/language/src/ast/operators.rs +++ b/schala-lang/language/src/ast/operators.rs @@ -4,84 +4,84 @@ use crate::tokenizing::TokenKind; #[derive(Debug, PartialEq, Clone)] pub struct PrefixOp { - sigil: Rc, + sigil: Rc, } impl PrefixOp { - pub fn from_sigil(sigil: &str) -> PrefixOp { - PrefixOp { sigil: Rc::new(sigil.to_string()) } - } + pub fn from_sigil(sigil: &str) -> PrefixOp { + PrefixOp { sigil: Rc::new(sigil.to_string()) } + } - pub fn sigil(&self) -> &str { - &self.sigil - } + pub fn sigil(&self) -> &str { + &self.sigil + } - pub fn is_prefix(op: &str) -> bool { - matches!(op, "+" | "-" | "!") - } + pub fn is_prefix(op: &str) -> bool { + matches!(op, "+" | "-" | "!") + } } #[derive(Debug, PartialEq, Clone)] pub struct BinOp { - sigil: Rc, + sigil: Rc, } impl BinOp { - pub fn from_sigil(sigil: &str) -> BinOp { - BinOp { sigil: Rc::new(sigil.to_string()) } - } + pub fn from_sigil(sigil: &str) -> BinOp { + BinOp { sigil: Rc::new(sigil.to_string()) } + } - pub fn sigil(&self) -> &str { - &self.sigil - } + pub fn sigil(&self) -> &str { + &self.sigil + } - pub fn from_sigil_token(tok: &TokenKind) -> Option { - let s = token_kind_to_sigil(tok)?; - Some(BinOp::from_sigil(s)) - } + pub fn from_sigil_token(tok: &TokenKind) -> Option { + let s = token_kind_to_sigil(tok)?; + Some(BinOp::from_sigil(s)) + } - pub fn min_precedence() -> i32 { - i32::min_value() - } - pub fn get_precedence_from_token(op_tok: &TokenKind) -> Option { - let s = token_kind_to_sigil(op_tok)?; - Some(binop_precedences(s)) - } + pub fn min_precedence() -> i32 { + i32::min_value() + } + pub fn get_precedence_from_token(op_tok: &TokenKind) -> Option { + let s = token_kind_to_sigil(op_tok)?; + Some(binop_precedences(s)) + } } -fn token_kind_to_sigil(tok: & TokenKind) -> Option<&str> { - use self::TokenKind::*; - Some(match tok { - Operator(op) => op.as_str(), - Period => ".", - Pipe => "|", - Slash => "/", - LAngleBracket => "<", - RAngleBracket => ">", - Equals => "=", - _ => return None - }) +fn token_kind_to_sigil(tok: &TokenKind) -> Option<&str> { + use self::TokenKind::*; + Some(match tok { + Operator(op) => op.as_str(), + Period => ".", + Pipe => "|", + Slash => "/", + LAngleBracket => "<", + RAngleBracket => ">", + Equals => "=", + _ => return None, + }) } fn binop_precedences(s: &str) -> i32 { - let default = 10_000_000; - match s { - "+" => 10, - "-" => 10, - "*" => 20, - "/" => 20, - "%" => 20, - "++" => 30, - "^" => 30, - "&" => 20, - "|" => 20, - ">" => 20, - ">=" => 20, - "<" => 20, - "<=" => 20, - "==" => 40, - "<=>" => 30, - "=" => 5, // Assignment shoudl have highest precedence - _ => default, - } + let default = 10_000_000; + match s { + "+" => 10, + "-" => 10, + "*" => 20, + "/" => 20, + "%" => 20, + "++" => 30, + "^" => 30, + "&" => 20, + "|" => 20, + ">" => 20, + ">=" => 20, + "<" => 20, + "<=" => 20, + "==" => 40, + "<=>" => 30, + "=" => 5, // Assignment shoudl have highest precedence + _ => default, + } } diff --git a/schala-lang/language/src/ast/visitor.rs b/schala-lang/language/src/ast/visitor.rs index 64725ac..161a217 100644 --- a/schala-lang/language/src/ast/visitor.rs +++ b/schala-lang/language/src/ast/visitor.rs @@ -3,17 +3,27 @@ use crate::ast::*; #[derive(Debug)] pub enum Recursion { Continue, - Stop + Stop, } pub trait ASTVisitor: Sized { - fn expression(&mut self, _expression: &Expression) -> Recursion { Recursion::Continue } - fn declaration(&mut self, _declaration: &Declaration, _id: &ItemId) -> Recursion { Recursion::Continue } + fn expression(&mut self, _expression: &Expression) -> Recursion { + Recursion::Continue + } + fn declaration(&mut self, _declaration: &Declaration, _id: &ItemId) -> Recursion { + Recursion::Continue + } - fn import(&mut self, _import: &ImportSpecifier) -> Recursion { Recursion::Continue } - fn module(&mut self, _module: &ModuleSpecifier) -> Recursion { Recursion::Continue } + fn import(&mut self, _import: &ImportSpecifier) -> Recursion { + Recursion::Continue + } + fn module(&mut self, _module: &ModuleSpecifier) -> Recursion { + Recursion::Continue + } - fn pattern(&mut self, _pat: &Pattern) -> Recursion { Recursion::Continue } + fn pattern(&mut self, _pat: &Pattern) -> Recursion { + Recursion::Continue + } } pub fn walk_ast(v: &mut V, ast: &AST) { @@ -32,12 +42,11 @@ pub fn walk_block(v: &mut V, block: &Block) { } Import(ref import_spec) => { v.import(import_spec); - }, - Module(ref module_spec) => { + } + Module(ref module_spec) => if let Recursion::Continue = v.module(module_spec) { walk_block(v, &module_spec.contents); - } - } + }, } } } @@ -50,12 +59,7 @@ pub fn walk_declaration(v: &mut V, decl: &Declaration, id: &ItemI FuncDecl(_sig, block) => { walk_block(v, block); } - Binding { - name: _, - constant: _, - type_anno: _, - expr, - } => { + Binding { name: _, constant: _, type_anno: _, expr } => { walk_expression(v, expr); } _ => (), @@ -76,16 +80,14 @@ pub fn walk_expression(v: &mut V, expr: &Expression) { PrefixExp(_, arg) => { walk_expression(v, arg); } - TupleLiteral(exprs) => { + TupleLiteral(exprs) => for expr in exprs { walk_expression(v, expr); - } - } - NamedStruct { name: _, fields } => { + }, + NamedStruct { name: _, fields } => for (_, expr) in fields.iter() { walk_expression(v, expr); - } - } + }, Call { f, arguments } => { walk_expression(v, f); for arg in arguments.iter() { @@ -102,10 +104,7 @@ pub fn walk_expression(v: &mut V, expr: &Expression) { walk_expression(v, indexer); } } - IfExpression { - discriminator, - body, - } => { + IfExpression { discriminator, body } => { if let Some(d) = discriminator.as_ref() { walk_expression(v, d); } @@ -126,18 +125,13 @@ pub fn walk_expression(v: &mut V, expr: &Expression) { ForBody::StatementBlock(block) => walk_block(v, block), }; } - Lambda { - params: _, - type_anno: _, - body, - } => { + Lambda { params: _, type_anno: _, body } => { walk_block(v, body); } - ListLiteral(exprs) => { + ListLiteral(exprs) => for expr in exprs { walk_expression(v, expr); - } - } + }, }; } } @@ -146,27 +140,20 @@ pub fn walk_if_expr_body(v: &mut V, body: &IfExpressionBody) { use IfExpressionBody::*; match body { - SimpleConditional { - then_case, - else_case, - } => { + SimpleConditional { then_case, else_case } => { walk_block(v, then_case); if let Some(block) = else_case.as_ref() { walk_block(v, block) } } - SimplePatternMatch { - pattern, - then_case, - else_case, - } => { + SimplePatternMatch { pattern, then_case, else_case } => { walk_pattern(v, pattern); walk_block(v, then_case); if let Some(block) = else_case.as_ref() { walk_block(v, block) } } - CondList(arms) => { + CondList(arms) => for arm in arms { match arm.condition { Condition::Pattern(ref pat) => { @@ -184,8 +171,7 @@ pub fn walk_if_expr_body(v: &mut V, body: &IfExpressionBody) { walk_expression(v, guard); } walk_block(v, &arm.body); - } - } + }, } } @@ -194,21 +180,18 @@ pub fn walk_pattern(v: &mut V, pat: &Pattern) { if let Recursion::Continue = v.pattern(pat) { match pat { - TuplePattern(patterns) => { + TuplePattern(patterns) => for pat in patterns { walk_pattern(v, pat); - } - } - TupleStruct(_, patterns) => { + }, + TupleStruct(_, patterns) => for pat in patterns { walk_pattern(v, pat); - } - } - Record(_, name_and_patterns) => { + }, + Record(_, name_and_patterns) => for (_, pat) in name_and_patterns { walk_pattern(v, pat); - } - } + }, _ => (), }; }