diff --git a/sketching/april_2025/closure_inputs.dm b/sketching/april_2025/closure_inputs.dm new file mode 100644 index 0000000..4185c3f --- /dev/null +++ b/sketching/april_2025/closure_inputs.dm @@ -0,0 +1,16 @@ +class Counter { + fld count: Int + + mut getAndIncrement() -> Int { + let result = count + count++ + result + } +} + +@Synthetic +class MyClosure(delegate: Counter) : MutClosure(Int, Int) -> Int |delegate| { + mut fn call(x: Int, y: Int) -> Int { + x + y + delegate.getAndIncrement() + } +} diff --git a/sketching/april_2025/iterator.dm b/sketching/april_2025/iterator.dm new file mode 100644 index 0000000..d562b0d --- /dev/null +++ b/sketching/april_2025/iterator.dm @@ -0,0 +1,14 @@ +pub type Iterator |backing: &Any| = mut fn () -> Option<&T ref backing> + +pub int Iterable { + ref fn iterator() -> Iterator(&self) +} + +fn main() { + let nums: List = [1, 2, 3] + let iterator: Iterator |backing = nums| = nums.iterator() + let first: &Int ref nums = iterator().unwrap() + let second: &Int ref nums = iterator().unwrap() + let third: &Int ref nums = iterator().unwrap() + println "${*first}, ${*second}, ${*third}" +} diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 4e8565b..f5deaa6 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -1,256 +1,507 @@ -use crate::vm::source_code_location::SourceCodeLocation; use pest::Parser; pub mod build; +pub mod unparse; + +// Operators #[derive(Debug)] -pub struct CompilationUnit { - namespace: Option, - declarations: Vec, +pub enum Operator { + Binary(BinaryOperator), + Unary(UnaryOperator), } -impl CompilationUnit { - pub fn namespace(&self) -> &Option { - &self.namespace - } +#[derive(Debug)] +pub enum BinaryOperator { + Or, + And, + EqualTo, + NotEqualTo, + Greater, + Less, + GreaterEqual, + LessEqual, + Add, + Subtract, + Multiply, + Divide, + Modulo, + LeftShift, + RightShift, +} - pub fn declarations(&self) -> &Vec { - &self.declarations - } +#[derive(Debug)] +pub enum UnaryOperator { + Not, + Negative, + PlusPlus, + MinusMinus, + CallOp, + Spread, +} + +// Names + +#[derive(Debug, Clone)] +pub struct Identifier { + pub name: String, } #[derive(Debug)] pub struct Fqn { - identifiers: Vec, + pub identifiers: Vec, } -impl Fqn { - pub fn new(identifiers: Vec) -> Self { - Fqn { identifiers } - } - - pub fn identifiers(&self) -> &Vec { - &self.identifiers - } - - pub fn push_identifier(&mut self, identifier: Identifier) { - self.identifiers.push(identifier); - } - - pub fn pop_identifier(&mut self) { - self.identifiers.pop(); - } -} +// Generic parameters #[derive(Debug)] -pub enum Declaration { - Interface { - identifier: Identifier, - is_extern: bool, - is_public: bool, - type_declaration: TypeDeclaration, - }, - Implementation { - identifier: Identifier, - is_extern: bool, - is_public: bool, - type_declaration: TypeDeclaration, - impl_ctor: Option, - }, - Module { - identifier: Identifier, - is_extern: bool, - is_public: bool, - declarations: Vec, - }, - Function(FunctionDeclaration), - Prop(Prop), - Field(Field), -} +pub struct GenericParameters(pub Vec); -#[derive(Debug)] -pub struct FunctionDeclaration { - source_code_location: SourceCodeLocation, - identifier: Identifier, - is_extern: bool, - is_public: bool, - parameters: Vec, - declared_type: Option, - block_statement: BlockStatement, -} - -impl FunctionDeclaration { - pub fn source_code_location(&self) -> &SourceCodeLocation { - &self.source_code_location - } - - pub fn identifier(&self) -> &Identifier { - &self.identifier - } - - pub fn block_statement(&self) -> &BlockStatement { - &self.block_statement - } -} - -#[derive(Debug)] -pub struct TypeDeclaration { - generics: Vec, - extends: Vec, - declarations: Vec, -} - -impl TypeDeclaration { - pub fn new( - generics: Vec, - extends: Vec, - declarations: Vec, - ) -> TypeDeclaration { - TypeDeclaration { - generics, - extends, - declarations, - } - } -} - -#[derive(Debug, Clone)] -pub struct Identifier { - name: String, -} - -impl Identifier { - pub fn name(&self) -> &str { - &self.name +impl GenericParameters { + pub fn is_empty(&self) -> bool { + self.0.is_empty() } } #[derive(Debug)] pub struct GenericParameter { identifier: Identifier, - bound: Option, } +// Generic arguments + #[derive(Debug)] -pub enum GenericBound { - Extends { fqn: Fqn }, - Super { fqn: Fqn }, +pub struct GenericArguments(pub Vec); + +impl GenericArguments { + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } } #[derive(Debug)] pub struct GenericArgument { - fqn: Fqn, + pub fqn: Fqn, } +// Type-use and components + #[derive(Debug)] pub struct TypeUse { - fqn: Fqn, - generics: Vec, + pub fqn: Fqn, + pub arguments: Option, } #[derive(Debug)] -pub struct ClassConstructor { - args: Vec, +pub enum TypeArguments { + Generics(GenericArguments), + Tuple(TupleArguments), + Function(FunctionTypeArguments), } -impl ClassConstructor { - pub fn new(args: Vec) -> Self { - ClassConstructor { args } +#[derive(Debug)] +pub struct TupleArguments(pub Vec); + +impl TupleArguments { + pub fn is_empty(&self) -> bool { + self.0.is_empty() } } #[derive(Debug)] -pub struct ClassMember { - is_field: bool, - identifier: Identifier, - type_use: Option +pub struct FunctionTypeArguments { + pub parameters: Parameters, + pub return_type: Box, } -impl ClassMember { - pub fn new(is_field: bool, identifier: Identifier, type_use: Option) -> Self { - ClassMember { - is_field, - identifier, - type_use - } +// Function components + +#[derive(Debug)] +pub struct Parameters(pub Vec); + +impl Parameters { + pub fn is_empty(&self) -> bool { + self.0.is_empty() } } #[derive(Debug)] -pub struct ImplCtorArg { - is_field: bool, +pub struct Parameter { identifier: Identifier, - r#type: Option, + type_use: TypeUse, } #[derive(Debug)] -pub struct Prop { - identifier: Identifier, - r#type: TypeUse, +pub struct ReturnType { + pub type_use: Box, + pub references: References, } #[derive(Debug)] -pub struct Field { - identifier: Identifier, - r#type: TypeUse, -} +pub struct References(pub Vec); -#[derive(Debug)] -pub struct BlockStatement { - statements: Vec, -} - -impl BlockStatement { - pub fn statements(&self) -> &Vec { - &self.statements +impl References { + pub fn is_empty(&self) -> bool { + self.0.is_empty() } } +#[derive(Debug)] +pub struct Reference { + pub identifier: Identifier, +} + +// Inputs + +#[derive(Debug)] +pub enum DelegateOrIdentifier { + Delegate, + Identifier(Identifier), +} + +#[derive(Debug)] +pub struct InputParameters(pub Vec); + +impl InputParameters { + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } +} + +#[derive(Debug)] +pub struct InputArguments(pub Vec); + +impl InputArguments { + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } +} + +#[derive(Debug)] +pub struct InputArgument { + pub lhs: DelegateOrIdentifier, + pub rhs: Identifier +} + +// Where guards + +#[derive(Debug)] +pub struct WhereGuards(pub Vec); + +impl WhereGuards { + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } +} + +#[derive(Debug)] +pub struct WhereGuard { + pub identifier: Identifier, + pub implements: ImplementsList +} + +// Implements + +#[derive(Debug)] +pub struct ImplementsList(pub Vec); + +impl ImplementsList { + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } +} + +// Top-level construct + +#[derive(Debug)] +pub struct CompilationUnit { + pub namespace: Option, + pub declarations: Vec, +} + +// Declarations allowed in each level + +#[derive(Debug)] +pub enum ModuleLevelDeclaration { + Type(TypeDeclaration), + Module(ModuleDeclaration), + Interface(InterfaceDeclaration), + Class(ClassDeclaration), + Function(FunctionDeclaration), + PlatformFunction(PlatformFunctionDeclaration), +} + +#[derive(Debug)] +pub enum InterfaceLevelDeclaration { + Type(TypeDeclaration), + Module(ModuleDeclaration), + Interface(InterfaceDeclaration), + Class(ClassDeclaration), + Function(InterfaceFunctionDeclaration), + OperatorFunction(InterfaceOperatorFunctionDeclaration), +} + +#[derive(Debug)] +pub enum ClassLevelDeclaration { + Type(TypeDeclaration), + Module(ModuleDeclaration), + Interface(InterfaceDeclaration), + Class(ClassDeclaration), + Function(FunctionDeclaration), + OperatorFunction(OperatorFunctionDeclaration), + PlatformFunction(PlatformFunctionDeclaration), + Field(FieldDeclaration), +} + +// Declarations + +#[derive(Debug)] +pub struct TypeDeclaration { + pub is_public: bool, + pub identifier: Identifier, + pub parameters: Option, + pub where_guards: WhereGuards, + pub rhs: TypeUse, +} + +#[derive(Debug)] +pub struct ModuleDeclaration { + pub is_public: bool, + pub identifier: Identifier, + pub declarations: Vec, +} + +#[derive(Debug)] +pub struct InterfaceDeclaration { + pub is_public: bool, + pub identifier: Identifier, + pub generics: GenericParameters, + pub inputs: InputParameters, + pub implements: ImplementsList, + pub where_guards: WhereGuards, + pub declarations: Vec, +} + +#[derive(Debug)] +pub struct ClassDeclaration { + pub is_public: bool, + pub identifier: Identifier, + pub generics: GenericParameters, + pub class_constructor: Option, + pub inputs: InputArguments, + pub implements: ImplementsList, + pub where_guards: WhereGuards, + pub declarations: Vec, +} + +// Function declarations and components + +#[derive(Debug)] +pub enum FunctionModifier { + Static, + Cons, + Mut, + Ref, + MutRef, +} + +#[derive(Debug)] +pub enum FunctionBody { + EqualsBody(Expression), + BlockBody(BlockStatement), + AliasBody(Identifier), +} + +#[derive(Debug)] +pub struct FunctionDeclaration { + pub is_public: bool, + pub modifier: Option, + pub generics: GenericParameters, + pub identifier: Identifier, + pub parameters: Parameters, + pub return_type: Option, + pub body: FunctionBody, +} + +#[derive(Debug)] +pub struct OperatorFunctionDeclaration { + pub is_public: bool, + pub modifier: Option, + pub generics: GenericParameters, + pub operator: Operator, + pub parameters: Parameters, + pub return_type: Option, + pub body: FunctionBody, +} + +#[derive(Debug)] +pub struct PlatformFunctionDeclaration { + pub is_public: bool, + pub modifier: Option, + pub generics: GenericParameters, + pub identifier: Identifier, + pub parameters: Parameters, + pub return_type: TypeUse, +} + +#[derive(Debug)] +pub struct InterfaceFunctionDeclaration { + pub modifier: Option, + pub generics: GenericParameters, + pub identifier: Identifier, + pub parameters: Parameters, + pub return_type: ReturnType, +} + +#[derive(Debug)] +pub struct InterfaceOperatorFunctionDeclaration { + pub modifier: Option, + pub generics: GenericParameters, + pub operator: Operator, + pub parameters: Parameters, + pub return_type: ReturnType, +} + +// Type components + +#[derive(Debug)] +pub enum TypeParameters { + Generic(GenericParameters), + Tuple(TupleParameters), + Function(FunctionTypeParameters), +} + +#[derive(Debug)] +pub struct TupleParameters(pub Vec); + +#[derive(Debug)] +pub struct FunctionTypeParameters { + pub parameters: Parameters, + pub return_type: TypeUse, +} + +// Class components + +#[derive(Debug)] +pub struct ClassConstructor(pub Vec); + +#[derive(Debug)] +pub struct ClassConstructorParameter { + pub is_field: bool, + pub identifier: Identifier, + pub declared_type: TypeUse +} + +#[derive(Debug)] +pub struct FieldDeclaration { + pub is_mutable: bool, + pub identifier: Identifier, + pub declared_type: TypeUse, +} + +// Statements + +#[derive(Debug)] +pub struct BlockStatement(pub Vec); + #[derive(Debug)] pub enum Statement { + BlockStatement(BlockStatement), CallStatement(CallExpression), - AssignStatement(AssignExpression), + VariableDeclarationStatement(VariableDeclarationStatement), + AssignStatement(AssignStatement), + ReturnStatement(ReturnStatement), + IfStatement(IfStatement), + IfElseStatement(IfElseStatement), + WhileStatement(WhileStatement), + ForStatement(ForStatement), +} + +#[derive(Debug)] +pub struct VariableDeclarationStatement { + is_mutable: bool, + identifier: Identifier, + declared_type: Option, + initializer: Option, +} + +#[derive(Debug)] +pub struct AssignStatement(pub AssignmentExpression); + +#[derive(Debug)] +pub struct ReturnStatement(pub Option); + +#[derive(Debug)] +pub struct IfStatement { + pub condition: Expression, + pub then_branch: BlockStatement, +} + +#[derive(Debug)] +pub struct IfElseStatement { + pub condition: Expression, + pub then_branch: BlockStatement, + pub else_ifs: ElseIfs, + pub else_branch: BlockStatement, +} + +#[derive(Debug)] +pub struct ElseIfs(pub Vec); + +#[derive(Debug)] +pub struct WhileStatement { + pub condition: Expression, + pub body: BlockStatement, +} + +#[derive(Debug)] +pub struct ForStatement { + pub variable: Identifier, + pub iterator: Expression, + pub body: BlockStatement, +} + +// Expressions + +#[derive(Debug)] +pub enum Expression { + Binary(BinaryExpression), + Unary(UnaryExpression), + Assignment(Box), + Call(CallExpression), + Literal(Literal) +} + +#[derive(Debug)] +pub struct BinaryExpression { + pub left: Box, + pub operator: BinaryOperator, + pub right: Box, +} + +#[derive(Debug)] +pub struct UnaryExpression { + pub operator: UnaryOperator, + pub expression: Box, +} + +#[derive(Debug)] +pub struct AssignmentExpression { + identifier: Identifier, + expression: Expression, } #[derive(Debug)] pub struct CallExpression { - receiver: Expression, - actuals_list: Vec, - source_code_location: SourceCodeLocation, -} - -impl CallExpression { - pub fn receiver(&self) -> &Expression { - &self.receiver - } - - pub fn actuals_list(&self) -> &Vec { - &self.actuals_list - } - - pub fn source_code_location(&self) -> &SourceCodeLocation { - &self.source_code_location - } + pub callee: Box, + pub arguments: CallArguments } #[derive(Debug)] -pub struct AssignExpression { - left: LValue, - right: Expression, -} +pub struct CallArguments(pub Vec); #[derive(Debug)] -pub enum Expression { - CallExpression(Box), - AssignExpression(Box), - LValue(Box), - Literal(Box), -} - -#[derive(Debug)] -pub enum LValue { - Fqn(Fqn), -} +pub struct CallArgument(pub Box); #[derive(Debug)] pub enum Literal { @@ -261,9 +512,3 @@ pub enum Literal { StringLiteral(String), BooleanLiteral(bool), } - -#[derive(Debug)] -pub struct Parameter { - identifier: Identifier, - declared_type: Option, -} diff --git a/src/ast/unparse.rs b/src/ast/unparse.rs new file mode 100644 index 0000000..c9922ba --- /dev/null +++ b/src/ast/unparse.rs @@ -0,0 +1,959 @@ +use crate::ast::*; + +macro_rules! to_unparse_vec { + ( $nodes:expr ) => { + $nodes + .iter() + .map(|node| node as &dyn Unparse) + .collect::>() + }; +} + +macro_rules! unparse_contained_declarations { + ( $declarations:expr, $buf:expr ) => { + if !$declarations.is_empty() { + write!($buf, "{{\n")?; + unparse_list($buf, "\n\n", &to_unparse_vec!($declarations)); + write!($buf, "\n}}")?; + } + }; +} + +macro_rules! unparse_ok { + () => { + Ok(()) + }; +} + +pub trait Unparse { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result; +} + +pub trait ListUnparse: Unparse { + fn prefix() -> &'static str { + "" + } + + fn separator() -> &'static str; + + fn suffix() -> &'static str { + "" + } + + fn inner(&self) -> Vec<&dyn Unparse>; +} + +impl Unparse for T { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + write!(buf, "{}", Self::prefix())?; + unparse_list(buf, Self::separator(), &self.inner())?; + write!(buf, "{}", Self::suffix())?; + unparse_ok!() + } +} + +fn unparse_list( + buf: &mut dyn std::fmt::Write, + sep: &str, + items: &[&dyn Unparse], +) -> std::fmt::Result { + for (i, item) in items.iter().enumerate() { + item.unparse(buf)?; + if i < items.len() - 1 { + write!(buf, "{}", sep)?; + } + } + Ok(()) +} + +fn unparse_comma_list(buf: &mut dyn std::fmt::Write, items: &[&dyn Unparse]) -> std::fmt::Result { + unparse_list(buf, ", ", items) +} + +/* Implementations */ + +/* Operators */ + +impl Unparse for Operator { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + use Operator::*; + match self { + Binary(op) => op.unparse(buf), + Unary(op) => op.unparse(buf), + } + } +} + +impl Unparse for BinaryOperator { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + use BinaryOperator::*; + match self { + Or => write!(buf, "||"), + And => write!(buf, "&&"), + EqualTo => write!(buf, "=="), + NotEqualTo => write!(buf, "!="), + Greater => write!(buf, ">"), + Less => write!(buf, "<"), + GreaterEqual => write!(buf, ">="), + LessEqual => write!(buf, "<="), + Add => write!(buf, "+"), + Subtract => write!(buf, "-"), + Multiply => write!(buf, "*"), + Divide => write!(buf, "/"), + Modulo => write!(buf, "%"), + LeftShift => write!(buf, "<<"), + RightShift => write!(buf, ">>"), + } + } +} + +impl Unparse for UnaryOperator { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + use UnaryOperator::*; + match self { + Not => write!(buf, "!"), + Negative => write!(buf, "-"), + PlusPlus => write!(buf, "++"), + MinusMinus => write!(buf, "--"), + CallOp => write!(buf, "()"), + Spread => write!(buf, "..."), + } + } +} + +/* Names */ + +impl Unparse for Identifier { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + write!(buf, "{}", self.name) + } +} + +impl ListUnparse for Fqn { + fn separator() -> &'static str { + "::" + } + + fn inner(&self) -> Vec<&dyn Unparse> { + to_unparse_vec!(self.identifiers) + } +} + +/* Generic Parameters */ + +impl ListUnparse for GenericParameters { + fn prefix() -> &'static str { + "<" + } + + fn separator() -> &'static str { + ", " + } + + fn suffix() -> &'static str { + ">" + } + + fn inner(&self) -> Vec<&dyn Unparse> { + to_unparse_vec!(self.0) + } +} + +impl Unparse for GenericParameter { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + self.identifier.unparse(buf) + } +} + +/* Generic arguments */ + +impl ListUnparse for GenericArguments { + fn prefix() -> &'static str { + "<" + } + + fn separator() -> &'static str { + ", " + } + + fn suffix() -> &'static str { + ">" + } + + fn inner(&self) -> Vec<&dyn Unparse> { + to_unparse_vec!(self.0) + } +} + +impl Unparse for GenericArgument { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + self.fqn.unparse(buf) + } +} + +/* TypeUse and components */ + +impl Unparse for TypeUse { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + self.fqn.unparse(buf)?; + if let Some(type_arguments) = &self.arguments { + type_arguments.unparse(buf)?; + } + unparse_ok!() + } +} + +impl Unparse for TypeArguments { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + use TypeArguments::*; + match self { + Generics(generic_arguments) => generic_arguments.unparse(buf), + Tuple(tuple_arguments) => tuple_arguments.unparse(buf), + Function(function_type_arguments) => function_type_arguments.unparse(buf), + } + } +} + +impl ListUnparse for TupleArguments { + fn prefix() -> &'static str { + "(" + } + + fn separator() -> &'static str { + ", " + } + + fn suffix() -> &'static str { + ")" + } + + fn inner(&self) -> Vec<&dyn Unparse> { + to_unparse_vec!(self.0) + } +} + +impl Unparse for FunctionTypeArguments { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + self.parameters.unparse(buf)?; + write!(buf, " ")?; + self.return_type.unparse(buf)?; + unparse_ok!() + } +} + +/* Function components */ + +impl ListUnparse for Parameters { + fn prefix() -> &'static str { + "(" + } + + fn separator() -> &'static str { + ", " + } + + fn suffix() -> &'static str { + ")" + } + + fn inner(&self) -> Vec<&dyn Unparse> { + to_unparse_vec!(self.0) + } +} + +impl Unparse for Parameter { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + self.identifier.unparse(buf)?; + write!(buf, ": ")?; + self.type_use.unparse(buf)?; + unparse_ok!() + } +} + +impl Unparse for ReturnType { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + write!(buf, "-> ")?; + self.type_use.unparse(buf)?; + if !self.references.is_empty() { + self.references.unparse(buf)?; + } + unparse_ok!() + } +} + +impl ListUnparse for References { + fn prefix() -> &'static str { + "ref " + } + + fn separator() -> &'static str { + ", " + } + + fn inner(&self) -> Vec<&dyn Unparse> { + to_unparse_vec!(self.0) + } +} + +impl Unparse for Reference { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + self.identifier.unparse(buf) + } +} + +/* Input parameters and arguments */ + +impl Unparse for DelegateOrIdentifier { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + use DelegateOrIdentifier::*; + match self { + Delegate => write!(buf, "delegate"), + Identifier(identifier) => identifier.unparse(buf), + } + } +} + +impl ListUnparse for InputParameters { + fn prefix() -> &'static str { + "|" + } + + fn separator() -> &'static str { + ", " + } + + fn suffix() -> &'static str { + "|" + } + + fn inner(&self) -> Vec<&dyn Unparse> { + to_unparse_vec!(self.0) + } +} + +impl ListUnparse for InputArguments { + fn prefix() -> &'static str { + "|" + } + + fn separator() -> &'static str { + ", " + } + + fn suffix() -> &'static str { + "|" + } + + fn inner(&self) -> Vec<&dyn Unparse> { + to_unparse_vec!(self.0) + } +} + +impl Unparse for InputArgument { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + self.lhs.unparse(buf)?; + write!(buf, " = ")?; + self.rhs.unparse(buf)?; + unparse_ok!() + } +} + +/* Where guards */ + +impl ListUnparse for WhereGuards { + fn prefix() -> &'static str { + "where " + } + + fn separator() -> &'static str { + ", " + } + + fn inner(&self) -> Vec<&dyn Unparse> { + to_unparse_vec!(self.0) + } +} + +impl Unparse for WhereGuard { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + self.identifier.unparse(buf)?; + write!(buf, " : ")?; + self.implements.unparse(buf)?; + unparse_ok!() + } +} + +/* Implements */ + +impl ListUnparse for ImplementsList { + fn prefix() -> &'static str { + ": " + } + + fn separator() -> &'static str { + " + " + } + + fn inner(&self) -> Vec<&dyn Unparse> { + to_unparse_vec!(self.0) + } +} + +/* Top-level construct */ + +impl Unparse for CompilationUnit { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + if let Some(namespace) = &self.namespace { + write!(buf, "ns ")?; + namespace.unparse(buf)?; + write!(buf, "\n\n")?; + } + unparse_list(buf, "\n\n", &to_unparse_vec!(self.declarations))?; + unparse_ok!() + } +} + +/* Declarations allowed in each level */ + +impl Unparse for ModuleLevelDeclaration { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + use ModuleLevelDeclaration::*; + match self { + Type(type_declaration) => type_declaration.unparse(buf), + Module(module_declaration) => module_declaration.unparse(buf), + Interface(interface_declaration) => interface_declaration.unparse(buf), + Class(class_declaration) => class_declaration.unparse(buf), + Function(function_declaration) => function_declaration.unparse(buf), + PlatformFunction(platform_function_declaration) => { + platform_function_declaration.unparse(buf) + } + } + } +} + +impl Unparse for InterfaceLevelDeclaration { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + use InterfaceLevelDeclaration::*; + match self { + Type(type_declaration) => type_declaration.unparse(buf), + Module(module_declaration) => module_declaration.unparse(buf), + Interface(interface_declaration) => interface_declaration.unparse(buf), + Class(class_declaration) => class_declaration.unparse(buf), + Function(interface_function_declaration) => interface_function_declaration.unparse(buf), + OperatorFunction(interface_operator_function_declaration) => { + interface_operator_function_declaration.unparse(buf) + } + } + } +} + +impl Unparse for ClassLevelDeclaration { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + use ClassLevelDeclaration::*; + match self { + Type(type_declaration) => type_declaration.unparse(buf), + Module(module_declaration) => module_declaration.unparse(buf), + Interface(interface_declaration) => interface_declaration.unparse(buf), + Class(class_declaration) => class_declaration.unparse(buf), + Function(function_declaration) => function_declaration.unparse(buf), + OperatorFunction(operator_function_declaration) => { + operator_function_declaration.unparse(buf) + } + PlatformFunction(platform_function_declaration) => { + platform_function_declaration.unparse(buf) + } + Field(field_declaration) => field_declaration.unparse(buf), + } + } +} + +/* Declarations */ + +impl Unparse for TypeDeclaration { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + if self.is_public { + write!(buf, "pub ")?; + } + write!(buf, "type ")?; + self.identifier.unparse(buf)?; + write!(buf, " ")?; + if let Some(type_parameters) = &self.parameters { + type_parameters.unparse(buf)?; + write!(buf, " ")?; + } + self.where_guards.unparse(buf)?; + write!(buf, "= ")?; + self.rhs.unparse(buf)?; + Ok(()) + } +} + +impl Unparse for ModuleDeclaration { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + if self.is_public { + write!(buf, "pub ")?; + } + write!(buf, "mod ")?; + self.identifier.unparse(buf)?; + unparse_contained_declarations!(self.declarations, buf); + unparse_ok!() + } +} + +impl Unparse for InterfaceDeclaration { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + if self.is_public { + write!(buf, "pub ")?; + } + write!(buf, "int ")?; + self.identifier.unparse(buf)?; + if !self.generics.is_empty() { + self.generics.unparse(buf)?; + write!(buf, " ")?; + } + if !self.inputs.is_empty() { + self.inputs.unparse(buf)?; + write!(buf, " ")?; + } + if !self.implements.is_empty() { + self.implements.unparse(buf)?; + write!(buf, " ")?; + } + if !self.where_guards.is_empty() { + self.where_guards.unparse(buf)?; + write!(buf, " ")?; + } + unparse_contained_declarations!(self.declarations, buf); + unparse_ok!() + } +} + +impl Unparse for ClassDeclaration { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + if self.is_public { + write!(buf, "pub ")?; + } + write!(buf, "class ")?; + self.identifier.unparse(buf)?; + if !self.generics.is_empty() { + self.generics.unparse(buf)?; + } + if let Some(class_constructor) = &self.class_constructor { + class_constructor.unparse(buf)?; + } + write!(buf, " ")?; + if !self.implements.is_empty() { + self.implements.unparse(buf)?; + write!(buf, " ")?; + } + if !self.inputs.is_empty() { + self.inputs.unparse(buf)?; + write!(buf, " ")?; + } + if !self.where_guards.is_empty() { + self.where_guards.unparse(buf)?; + write!(buf, " ")?; + } + unparse_contained_declarations!(self.declarations, buf); + unparse_ok!() + } +} + +/* Function declarations and components */ + +impl Unparse for FunctionModifier { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + use FunctionModifier::*; + match self { + Static => write!(buf, "static"), + Cons => write!(buf, "cons"), + Mut => write!(buf, "mut"), + Ref => write!(buf, "ref"), + MutRef => write!(buf, "mut ref"), + } + } +} + +impl Unparse for FunctionBody { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + use FunctionBody::*; + match self { + EqualsBody(expression) => { + write!(buf, "= ")?; + expression.unparse(buf) + } + BlockBody(body) => body.unparse(buf), + AliasBody(identifier) => { + write!(buf, "alias ")?; + identifier.unparse(buf) + } + } + } +} + +impl Unparse for FunctionDeclaration { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + if self.is_public { + write!(buf, "pub ")?; + } + if let Some(modifier) = &self.modifier { + modifier.unparse(buf)?; + write!(buf, " ")?; + } + write!(buf, "fn ")?; + self.generics.unparse(buf)?; + write!(buf, " ")?; + self.identifier.unparse(buf)?; + self.parameters.unparse(buf)?; + write!(buf, " ")?; + if let Some(return_type) = &self.return_type { + return_type.unparse(buf)?; + write!(buf, " ")?; + } + self.body.unparse(buf)?; + unparse_ok!() + } +} + +impl Unparse for OperatorFunctionDeclaration { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + if self.is_public { + write!(buf, "pub ")?; + } + if let Some(modifier) = &self.modifier { + modifier.unparse(buf)?; + write!(buf, " ")?; + } + self.operator.unparse(buf)?; + write!(buf, " ")?; + self.parameters.unparse(buf)?; + write!(buf, " ")?; + if let Some(return_type) = &self.return_type { + return_type.unparse(buf)?; + write!(buf, " ")?; + } + self.body.unparse(buf)?; + unparse_ok!() + } +} + +impl Unparse for PlatformFunctionDeclaration { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + if self.is_public { + write!(buf, "pub ")?; + } + write!(buf, "platform fn ")?; + if !self.generics.is_empty() { + self.generics.unparse(buf)?; + write!(buf, " ")?; + } + self.identifier.unparse(buf)?; + self.parameters.unparse(buf)?; + write!(buf, " ")?; + self.return_type.unparse(buf)?; + unparse_ok!() + } +} + +impl Unparse for InterfaceFunctionDeclaration { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + if let Some(modifier) = &self.modifier { + modifier.unparse(buf)?; + write!(buf, " ")?; + } + if !self.generics.is_empty() { + self.parameters.unparse(buf)?; + write!(buf, " ")?; + } + self.identifier.unparse(buf)?; + self.parameters.unparse(buf)?; + write!(buf, " ")?; + self.return_type.unparse(buf)?; + unparse_ok!() + } +} + +impl Unparse for InterfaceOperatorFunctionDeclaration { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + if let Some(modifier) = &self.modifier { + modifier.unparse(buf)?; + write!(buf, " ")?; + } + write!(buf, "op ")?; + if !self.generics.is_empty() { + self.generics.unparse(buf)?; + write!(buf, " ")?; + } + self.operator.unparse(buf)?; + write!(buf, " ")?; + self.parameters.unparse(buf)?; + write!(buf, " ")?; + self.return_type.unparse(buf)?; + unparse_ok!() + } +} + +/* Type components */ + +impl Unparse for TypeParameters { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + use TypeParameters::*; + match self { + Generic(generic_parameters) => generic_parameters.unparse(buf), + Tuple(tuple_parameters) => tuple_parameters.unparse(buf), + Function(function_type_parameters) => function_type_parameters.unparse(buf), + } + } +} + +impl ListUnparse for TupleParameters { + fn prefix() -> &'static str { + "(" + } + + fn separator() -> &'static str { + ", " + } + + fn suffix() -> &'static str { + ")" + } + + fn inner(&self) -> Vec<&dyn Unparse> { + to_unparse_vec!(self.0) + } +} + +impl Unparse for FunctionTypeParameters { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + self.parameters.unparse(buf)?; + write!(buf, " ")?; + self.return_type.unparse(buf)?; + unparse_ok!() + } +} + +/* Class components */ + +impl ListUnparse for ClassConstructor { + fn prefix() -> &'static str { + "(" + } + + fn separator() -> &'static str { + ", " + } + + fn suffix() -> &'static str { + ")" + } + + fn inner(&self) -> Vec<&dyn Unparse> { + to_unparse_vec!(self.0) + } +} + +impl Unparse for ClassConstructorParameter { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + if self.is_field { + write!(buf, "fld ")?; + } + self.identifier.unparse(buf)?; + write!(buf, ": ")?; + self.declared_type.unparse(buf)?; + unparse_ok!() + } +} + +impl Unparse for FieldDeclaration { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + if self.is_mutable { + write!(buf, "mut ")?; + } + self.identifier.unparse(buf)?; + write!(buf, ": ")?; + self.declared_type.unparse(buf)?; + unparse_ok!() + } +} + +/* Statements */ + +impl ListUnparse for BlockStatement { + fn prefix() -> &'static str { + "{\n" + } + + fn separator() -> &'static str { + "\n" + } + + fn suffix() -> &'static str { + "\n}" + } + + fn inner(&self) -> Vec<&dyn Unparse> { + to_unparse_vec!(self.0) + } +} + +impl Unparse for Statement { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + use Statement::*; + match self { + BlockStatement(statement) => statement.unparse(buf), + CallStatement(call_expression) => call_expression.unparse(buf), + VariableDeclarationStatement(declaration) => declaration.unparse(buf), + AssignStatement(assign_statement) => assign_statement.unparse(buf), + ReturnStatement(return_expression) => return_expression.unparse(buf), + IfStatement(if_statement) => if_statement.unparse(buf), + IfElseStatement(if_else_statement) => if_else_statement.unparse(buf), + WhileStatement(while_statement) => while_statement.unparse(buf), + ForStatement(for_statement) => for_statement.unparse(buf), + }?; + write!(buf, "\n") + } +} + +impl Unparse for VariableDeclarationStatement { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + write!(buf, "let ")?; + if self.is_mutable { + write!(buf, "mut ")?; + } + self.identifier.unparse(buf)?; + if let Some(declared_type) = &self.declared_type { + write!(buf, ": ")?; + declared_type.unparse(buf)?; + } + if let Some(initializer) = &self.initializer { + write!(buf, " = ")?; + initializer.unparse(buf)?; + } + unparse_ok!() + } +} + +impl Unparse for AssignStatement { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + self.0.unparse(buf) + } +} + +impl Unparse for ReturnStatement { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + write!(buf, "return")?; + if let Some(expression) = &self.0 { + write!(buf, " ")?; + expression.unparse(buf)?; + } + unparse_ok!() + } +} + +impl Unparse for IfStatement { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + write!(buf, "if ")?; + self.condition.unparse(buf)?; + write!(buf, " {{\n")?; + self.then_branch.unparse(buf)?; + write!(buf, "\n}}")?; + unparse_ok!() + } +} + +impl Unparse for IfElseStatement { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + write!(buf, "if ")?; + self.condition.unparse(buf)?; + write!(buf, " ")?; + self.then_branch.unparse(buf)?; + write!(buf, " ")?; + self.else_ifs.unparse(buf)?; + write!(buf, "else ")?; + self.else_branch.unparse(buf)?; + unparse_ok!() + } +} + +impl Unparse for ElseIfs { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + for if_statement in &self.0 { + write!(buf, " else ")?; + if_statement.unparse(buf)?; + write!(buf, " ")?; + } + unparse_ok!() + } +} + +impl Unparse for WhileStatement { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + write!(buf, "while ")?; + self.condition.unparse(buf)?; + write!(buf, " ")?; + self.body.unparse(buf)?; + unparse_ok!() + } +} + +impl Unparse for ForStatement { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + write!(buf, "for ")?; + self.variable.unparse(buf)?; + write!(buf, " in ")?; + self.iterator.unparse(buf)?; + write!(buf, " ")?; + self.body.unparse(buf)?; + unparse_ok!() + } +} + +/* Expressions */ + +impl Unparse for AssignmentExpression { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + self.identifier.unparse(buf)?; + write!(buf, " = ")?; + self.expression.unparse(buf)?; + unparse_ok!() + } +} + +impl Unparse for Expression { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + todo!() + } +} + +impl Unparse for CallExpression { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + self.callee.unparse(buf)?; + self.arguments.unparse(buf)?; + unparse_ok!() + } +} + +impl ListUnparse for CallArguments { + fn prefix() -> &'static str { + "(" + } + + fn separator() -> &'static str { + ", " + } + + fn suffix() -> &'static str { + ")" + } + + fn inner(&self) -> Vec<&dyn Unparse> { + to_unparse_vec!(self.0) + } +} + +impl Unparse for CallArgument { + fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { + self.0.unparse(buf) + } +} diff --git a/src/parser/deimos.pest b/src/parser/deimos.pest index 5a23a88..5bbe47c 100644 --- a/src/parser/deimos.pest +++ b/src/parser/deimos.pest @@ -1,78 +1,78 @@ -// Top-level constructs -CompilationUnit = { SOI ~ Namespace? ~ ModuleLevelDeclaration* ~ EOI } -Namespace = { "ns" ~ FullyQualifiedName } +// Keywords +Ns = { "ns" } +TypeKw = { "type" } +Mod = { "mod" } +Int = { "int" } +ClassKw = { "class" } +Platform = { "platform" } +Pub = { "pub" } +Fld = { "fld" } +Impl = { "impl" } +Mut = { "mut" } +Cons = { "cons" } +Static = { "static" } +Ref = { "ref" } +Def = { "def" } +Where = { "where" } +Infer = { "infer" } +Void = { "Void" } +Delegate = { "delegate" } +Let = { "let" } +Fn = { "fn" } +Op = { "op" } -CommonDeclaration = { Interface | Class | Module | Function | OperatorFunction } -ModuleLevelDeclaration = { Declare? ~ Public? ~ CommonDeclaration } -InterfaceLevelDeclaration = { CommonDeclaration } -ClassLevelDeclaration = { Declare? ~ Public? ~ ( CommonDeclaration | ClassMember ) } - -// Module -Module = { "mod" ~ Identifier ~ "{" ~ ModuleLevelDeclaration* ~ "}" } - -// Interface -Interface = { "int" ~ Identifier ~ GenericParameters? ~ ExtendsList? ~ ( "{" ~ InterfaceLevelDeclaration* ~ "}" )? } - -// Class -Class = { "class" ~ Identifier ~ GenericParameters? ~ ClassConstructor? ~ ExtendsList? ~ ( "{" ~ ClassLevelDeclaration* ~ "}" )? } -ClassMember = { Field? ~ Identifier ~ TypeAnnotation? } - -// Class Constructor -ClassConstructor = { "(" ~ ClassMemberList? ~ ")" } -ClassMemberList = { ClassMember ~ ( "," ~ ClassMember )* } - -// Various Keywords -Declare = { "decl" } -Public = { "pub" } -Field = { "fld" } -Implementation = { "impl" } -Mutable = { "mut" } -Consume = { "cons" } -Reference = { "ref" } -Define = { "def" } - -// Fqn and identifier -FullyQualifiedName = { Identifier ~ ( "::" ~ Identifier )* } - -Identifier = @{ IdentifierStartChar ~ IdentifierChar* } -IdentifierStartChar = { 'a'..'z' | 'A'..'Z' | "_" } -IdentifierChar = { 'a'..'z' | 'A'..'Z' | '0'..'9' | "_" } - -// Type constructs -ExtendsList = { ":" ~ TypeUse ~ ( "+" ~ TypeUse )* } -TypeAnnotation = { ":" ~ TypeUse } -TypeUse = { FullyQualifiedName ~ GenericArguments? } - -// Generic arguments given to a TypeUse or function calls -GenericArguments = { "<" ~ FullyQualifiedName ~ ( "," ~ FullyQualifiedName )* ~ ">" } - -// Generic parameters (for when types are declared) -GenericParameters = { "<" ~ Identifier ~ ( "," ~ Identifier )* ~ ">" } - -// Function -Function = { ( Implementation | Define )? - ~ ( Consume | Mutable )? - ~ Reference? - ~ "fn" - ~ GenericParameters? - ~ Identifier - ~ "(" ~ Parameters? ~ ")" - ~ ReturnType? - ~ ( FunctionAlias | FunctionEqualsBody | BlockStatement )? +// Keywords as a rule (for preventing identifiers with keywords, etc.) +Keyword = { + Ns + | TypeKw + | Mod + | Int + | ClassKw + | Platform + | Pub + | Fld + | Impl + | Mut + | Cons + | Static + | Ref + | Def + | Where + | Infer + | Void + | Delegate + | Let + | Fn + | Op } -ReturnType = { "->" ~ Reference? ~ TypeUse } -FunctionAlias = { "alias" ~ FullyQualifiedName } -OperatorFunction = { ( Implementation | Define )? - ~ ( Consume | Mutable )? - ~ Reference? - ~ "op" - ~ Operator - ~ "(" ~ Parameters? ~ ")" - ~ ReturnType? - ~ ( FunctionAlias | FunctionEqualsBody | BlockStatement )? -} -Operator = { Or +// Symbols +Ellipsis = { "..." } +Underscore = { "_" } + +// Operators +Or = { "||" } +And = { "&&" } +EqualTo = { "==" } +NotEqualTo = { "!=" } +Greater = { ">" } +Less = { "<" } +GreaterEqual = { ">=" } +LessEqual = { "<=" } +Add = { "+" } +Subtract = { "-" } +Multiply = { "*" } +Divide = { "/" } +Modulo = { "%" } +Not = { "!" } +Negative = { "-" } +PlusPlus = { "++" } +MinusMinus = { "--" } +CallOp = { "()" } +Spread = { Ellipsis } + +Operator = { + Or | And | EqualTo | NotEqualTo @@ -85,93 +85,691 @@ Operator = { Or | Multiply | Divide | Modulo + | Not + | Negative + | PlusPlus + | MinusMinus | CallOp + | Spread } -CallOp = { "()" } +// Commonly shared constructs -Parameters = { Parameter ~ ( "," ~ Parameter )* } -Parameter = { Identifier ~ TypeAnnotation? } +FullyQualifiedName = { + Identifier + ~ ( "::" ~ Identifier )* +} -FunctionEqualsBody = { "=" ~ Expression } +Identifier = @{ + ( Keyword ~ IdentifierChar | !Keyword ~ IdentifierStartChar ) + ~ IdentifierChar* +} + +IdentifierStartChar = { + 'a'..'z' + | 'A'..'Z' + | "_" +} + +IdentifierChar = { + 'a'..'z' + | 'A'..'Z' + | '0'..'9' + | "_" +} + +// In general: +// Arguments = usage +// Parameters = declaration + +TypeUse = { + FullyQualifiedName + ~ ( + GenericArguments ~ InputArguments? + | TupleGenericArguments + | FunctionGenericArguments ~ FunctionInputArguments? + | InputArguments + )? +} + +GenericArguments = { + "<" + ~ FullyQualifiedName + ~ ( "," ~ FullyQualifiedName )* + ~ ">" +} + +InputArguments = { + "|" + ~ ( + InputArgument + ~ ( "," ~ InputArgument )* + )? + ~ "|" +} + +InputArgument = { + Identifier + ~ ( "=" ~ Identifier ) +} + +TupleGenericArguments = { + "(" + ~ ( + FullyQualifiedName + ~ ( "," ~ FullyQualifiedName )* + )? + ~ ")" +} + +FunctionGenericArguments = { + TupleGenericArguments + ~ ReturnTypeGenericArgument + ~ FunctionInputArguments? +} + +ReturnTypeGenericArgument = { + "->" + ~ ( Void | FullyQualifiedName ) + ~ RefList? +} + +RefList = { + Ref + ~ Identifier + ~ ( "," ~ Identifier )* +} + +FunctionInputArguments = { + "|" + ~ ( + FunctionInputArgument + ~ ( "," ~ FunctionInputArgument )* + )? + ~ "|" +} + +FunctionInputArgument = { + ( Delegate | Identifier ) + ~ ( "=" ~ Identifier ) +} + +// Generic Parameters + +GenericParameters = { + "<" + ~ Identifier + ~ ( "," ~ Identifier )* + ~ ">" +} + +InputParameters = { + "|" + ~ InputParameter + ~ ( "," ~ InputParameter )* + ~ "|" +} + +InputParameter = { + Identifier + ~ ":" + ~ TypeUse +} + +TupleGenericParameters = { + "(" + ~ ( + Identifier + ~ ( "," ~ Identifier )* + )? + ~ ")" +} + +FunctionGenericParameters = { + TupleGenericParameters + ~ FunctionGenericParameterReturnType +} + +FunctionGenericParameterReturnType = { + "->" + ~ ( Void | Identifier ) + ~ RefList? +} + +FunctionInputParameters = { + "|" + ~ FunctionInputParameter + ~ ( "," ~ FunctionInputParameter )* + ~ "|" +} + +FunctionInputParameter = { + ( Delegate | Identifier ) + ~ ":" + ~ TypeUse +} + +ImplementsList = { + ":" + ~ TypeUse + ~ ( "+" ~ TypeUse ) +} + +WhereGuards = { + Where + ~ WhereGuard + ~ ( "," ~ WhereGuard )* +} + +WhereGuard = { + Identifier + ~ ImplementsList +} + +// Top-level constructs + +CompilationUnit = { + SOI + ~ Namespace? + ~ ModuleLevelDeclaration* + ~ EOI +} + +Namespace = { + Ns + ~ FullyQualifiedName +} + +// Organizational declarations + +ModuleLevelDeclaration = { + Type + | Module + | Interface + | Class + | FunctionDefinition + | PlatformFunction +} + +InterfaceLevelDeclaration = { + Type + | Module + | Interface + | Class + | InterfaceFunction + | InterfaceDefaultFunction + | InterfaceOperatorFunction + | InterfaceDefaultOperatorFunction +} + +ClassLevelDeclaration = { + Type + | Module + | Interface + | Class + | FunctionDefinition + | OperatorFunctionDefinition + | PlatformFunction + | Field +} + +// Main organizational constructs + +Type = { + Pub? + ~ TypeKw + ~ Identifier + ~ GenericParameters? + ~ TypeWhereGuards? + ~ "=" + ~ TypeUse +} + +Module = { + Pub? + ~ Mod + ~ Identifier + ~ "{" ~ ModuleLevelDeclaration* ~ "}" +} + +Interface = { + Pub? + ~ Int + ~ Identifier + ~ InterfaceGenericParametersAndInputs? + ~ ImplementsList? + ~ WhereGuards? + ~ ( "{" ~ InterfaceLevelDeclaration* ~ "}" )? +} + +Class = { + Pub? + ~ ClassKw + ~ Identifier + ~ GenericParameters? + ~ ClassConstructor? + ~ ImplementsList? + ~ InputArguments? + ~ WhereGuards? + ~ ( "{" ~ ClassLevelDeclaration* ~ "}" )? +} + +// Type + +TypeWhereGuards = { + Where + ~ TypeWhereGuard + ~ ( "," ~ TypeWhereGuard )* +} + +TypeWhereGuard = { + Identifier + ~ ":" + ~ TypeTypeUse + ~ ( "+" ~ TypeTypeUse )* +} + +TypeTypeUse = { + FullyQualifiedName + ~ TypeTypeArguments? +} + +TypeTypeArguments = { + TypeGenericArguments + | TypeGenericFunctionArguments + | TypeGenericTupleArguments +} + +TypeGenericArguments = { + "<" + ~ TypeGenericArgument + ~ ( "," ~ TypeGenericArgument )* + ~ ">" +} + +TypeGenericArgument = { + Underscore + | FullyQualifiedName + | ( Infer ~ Identifier ) +} + +TypeGenericTupleArguments = { + "(" + ~ ( + TypeGenericTupleArgument + ~ ( "," ~ TypeGenericTupleArgument )* + )? + ~ ")" +} + +TypeGenericTupleArgument = { + Underscore + | FullyQualifiedName + | ( Infer ~ Identifier ) + | ( Ellipsis ~ Underscore ) + | ( Ellipsis ~ Infer ~ Identifier ) +} + +TypeGenericFunctionArguments = { + TypeGenericTupleArguments + ~ TypeGenericArguments? + ~ TypeFunctionReturnType +} + +TypeFunctionReturnType = { + "->" + ~ ( Void | FullyQualifiedName ) + ~ RefList? +} + +// Interface + +InterfaceGenericParametersAndInputs = { + GenericParameters ~ InputParameters? + | TupleGenericParameters + | FunctionGenericParameters ~ FunctionInputParameters? + | InputParameters +} + +InterfaceFunction = { + ( + Static + | Cons + | ( Mut ~ Ref? ) + )? + ~ Fn + ~ GenericParameters? + ~ Identifier + ~ Parameters + ~ ReturnType + ~ WhereGuards? +} + +InterfaceDefaultFunction = { + Def + ~ ( + Static + | Cons + | ( Mut ~ Ref? ) + )? + ~ Fn + ~ GenericParameters? + ~ Identifier + ~ Parameters + ~ ReturnType + ~ WhereGuards? + ~ FunctionBody +} + +InterfaceOperatorFunction = { + ( + Cons + | ( Mut ~ Ref? ) + )? + ~ Op + ~ Operator + ~ Parameters + ~ ReturnType + ~ RefList? + ~ WhereGuards? // TODO: decide if we want this for interface op functions +} + +InterfaceDefaultOperatorFunction = { + Def + ~ ( + Cons + | ( Mut ~ Ref? ) + )? + ~ Op + ~ Operator + ~ Parameters + ~ ReturnType + ~ RefList? + ~ WhereGuards? + ~ FunctionBody +} + +// Class constructs + +ClassConstructor = { + "(" + ~ DataMember + ~ ( "," ~ DataMember )* + ~ ")" +} + +DataMember = { + Property + | Field +} + +Property = { + Mut? + ~ Identifier + ~ ":" + ~ TypeUse +} + +Field = { + Mut? + ~ Fld + ~ Identifier + ~ ":" + ~ TypeUse +} + +// Function constructs +FunctionModifier = { + Static + | Cons + | Mut? Ref? +} + +FunctionDefinition = { + Pub? + ~ FunctionModifier + ~ Fn + ~ GenericParameters? + ~ Identifier + ~ Parameters + ~ ReturnType? + ~ FunctionBody +} + +OperatorFunctionDefinition = { + Pub? + ~ FunctionModifier + ~ Op + ~ Operator + ~ Parameters + ~ ReturnType? + ~ FunctionBody +} + +PlatformFunction = { + Pub? + ~ FunctionModifier + ~ Platform + ~ Fn + ~ GenericParameters + ~ Identifier + ~ Parameters + ~ ReturnType +} + +Parameters = { + "(" + ~ ( + Parameter + ~ ( "," ~ Parameter )* + )? + ~ ")" +} + +Parameter = { + Identifier + ~ ":" + ~ TypeUse +} + +ReturnType = { + "->" + ~ ( Void | TypeUse ) + ~ RefList? +} + +FunctionBody = { + FunctionEqualsBody + | FunctionBlockBody + | FunctionAliasBody +} + +FunctionEqualsBody = { + "=" + ~ Expression +} + +FunctionBlockBody = { + "{" + ~ Statement* + ~ "}" +} + +FunctionAliasBody = { + "alias" + ~ Identifier +} // Statements -BlockStatement = { "{" ~ Statement* ~ "}" } -Statement = { VariableDeclaration | CallExpression | AssignmentExpression } -VariableDeclaration = { "let" ~ Mutable? ~ Identifier ~ TypeAnnotation? ~ ( "=" ~ Expression )? } +BlockStatement = { + "{" + ~ Statement* + ~ "}" +} + +Statement = { + BlockStatement + | VariableDeclaration + | AssignmentExpression +} + +VariableDeclaration = { + Let + ~ Mut? + ~ Identifier + ~ ( ":" ~ TypeUse )? + ~ ( "=" ~ Expression )? +} // Expressions + Expression = { OrExpression } -OrExpression = { AndExpression ~ ( Or ~ AndExpression )* } -AndExpression = { EqualityExpression ~ ( And ~ EqualityExpression )* } -Or = { "||" } -And = { "&&" } +OrExpression = { + AndExpression + ~ ( Or ~ Expression )* +} -EqualityExpression = { ComparisonExpression ~ ( ( EqualTo | NotEqualTo ) ~ ComparisonExpression )* } -EqualTo = { "==" } -NotEqualTo = { "!=" } +AndExpression = { + EqualityExpression + ~ ( And ~ Expression )* +} -ComparisonExpression = { AdditiveExpression ~ ( ( Greater | Less | GreaterEqual | LessEqual ) ~ AdditiveExpression )* } -Greater = { ">" } -Less = { "<" } -GreaterEqual = { ">=" } -LessEqual = { "<=" } +EqualityExpression = { + ComparisonExpression + ~ ( + ( EqualTo | NotEqualTo ) + ~ Expression + )* +} -AdditiveExpression = { MultiplicativeExpression ~ ( ( Add | Subtract ) ~ MultiplicativeExpression )* } -Add = { "+" } -Subtract = { "-" } +ComparisonExpression = { + AdditiveExpression + ~ ( + ( Greater | Less | GreaterEqual | LessEqual ) + ~ Expression + )* +} -MultiplicativeExpression = { UnaryExpression ~ ( ( Multiply | Divide | Modulo ) ~ UnaryExpression )* } -Multiply = { "*" } -Divide = { "/" } -Modulo = { "%" } +AdditiveExpression = { + MultiplicativeExpression + ~ ( + ( Add | Subtract ) + ~ Expression + )* +} -UnaryExpression = { ( Not | Negative )* ~ PrimaryExpression ~ ( Call | ( PlusPlus | MinusMinus ) )* } -Not = { "!" } -Negative = { "-" } -PlusPlus = { "++" } -MinusMinus = { "--" } +MultiplicativeExpression = { + SpreadExpression + ~ ( + ( Multiply | Divide | Modulo ) + ~ Expression + )* +} -PrimaryExpression = { Literal | ObjectAccess | ParenthesizedExpression } -ParenthesizedExpression = { "(" ~ Expression ~ ")" } +SpreadExpression = { + UnaryExpression + ~ Spread + ~ Expression +} +UnaryExpression = { + ( Not | Negative )* + ~ PrimaryExpression + ~ ( ( NoParenthesesCall | ParenthesesCall )+ | ( PlusPlus | MinusMinus ) )? +} -// Call -CallExpression = { PrimaryExpression ~ Call+ } -Call = { GenericArguments? ~ CallArguments } -ExpressionList = { Expression ~ ( "," ~ Expression )* } -CallArguments = { - ( "(" ~ ExpressionList? ~ ")" ) - | ExpressionList +PrimaryExpression = { + Literal + | ObjectAccess + | ParenthesizedExpression +} + +ParenthesizedExpression = { + "(" + ~ Expression + ~ ")" +} + +// Calls + +ParenthesesCall = { + TurboFish? + ~ "(" + ~ ExpressionList? + ~ ")" +} + +NoParenthesesCall = { + TurboFish? + ~ ExpressionList +} + +TurboFish = { + "::" + ~ GenericArguments +} + +ExpressionList = { + Expression + ~ ( "," ~ Expression )* } // Assignment -AssignmentExpression = { ObjectAccess ~ "=" ~ Expression } +AssignmentExpression = { + ObjectAccess + ~ "=" + ~ Expression +} // Object -ObjectAccess = { FullyQualifiedName ~ ( "." ~ Identifier )* } +ObjectAccess = { + FullyQualifiedName + ~ ( "." ~ Identifier )* +} // Literals -Literal = { NumberLiteral | StringLiteral | BooleanLiteral | NullLiteral } +Literal = { + NumberLiteral + | StringLiteral + | BooleanLiteral +} -NumberLiteral = { LongLiteral | IntLiteral } +NumberLiteral = { + LongLiteral + | IntLiteral + | DoubleLiteral +} IntLiteral = { NumberBase } + LongLiteral = ${ NumberBase ~ "L" } -NumberBase = { DecimalBase | BinaryBase | HexadecimalBase } +DoubleLiteral = ${ DecimalBase ~ "." ~ Digit+ } + +NumberBase = { + DecimalBase + | BinaryBase + | HexadecimalBase +} DecimalBase = @{ DecimalStartDigit ~ Digit* } + BinaryBase = @{ "0b" ~ Digit* } + DecimalStartDigit = { '1'..'9' } + Digit = { '0'..'9'+ } + HexadecimalBase = @{ "0x" ~ HexadecimalDigit+ } + HexadecimalDigit = { '0'..'9' | 'a'..'f' } StringLiteral = ${ "\"" ~ StringInner ~ "\"" } + StringInner = @{ StringChar* } + StringChar = { !( "\"" | "\\" ) ~ ANY | "\\" ~ ( "\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t" ) @@ -180,6 +778,4 @@ StringChar = { BooleanLiteral = { "true" | "false" } -NullLiteral = { "null" } - WHITESPACE = _{ " " | "\t" | "\n" | "\r" }