diff --git a/boring/parse.py b/boring/parse.py index bb6f253..dfeff23 100644 --- a/boring/parse.py +++ b/boring/parse.py @@ -202,14 +202,6 @@ class Impl: functions: List[Function] -@dataclass -class FunctionDeclartation: - name: str - arguments: List[VariableDeclaration] - return_type: TypeUsage - type: TypeUsage - - TraitItem = Union[FunctionDeclaration, Function] diff --git a/src/ast.rs b/src/ast.rs index de4d145..b5f8e04 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1,6 +1,56 @@ +use std::collections::HashMap; use crate::types; +pub struct IdGenerator { + counter: i64, +} + +impl IdGenerator { + pub fn new() -> Self { + IdGenerator{counter: 0} + } + + pub fn next(&mut self) -> i64 { + self.counter += 1; + self.counter + } +} + +pub fn new_named(name: String) -> { + ast::TypeUsage::Named(ast::NamedTypeUsage{ + name: ast::Identifier{ + name: ast::Spanned{ + span: ast::Span{left: 0, right: 0}, //todo: figure out a sane value for these + value: name, + } + } + ) +} + +pub fn new_unit() -> { + ast::TypeUsage::Named(ast::NamedTypeUsage{ + name: ast::Identifier{ + name: ast::Spanned{ + span: ast::Span{left: 0, right: 0}, //todo: figure out a sane value for these + value: "()".to_string(), + } + } + ) +} + +pub fn new_never() -> { + ast::TypeUsage::Named(ast::NamedTypeUsage{ + name: ast::Identifier{ + name: ast::Spanned{ + span: ast::Span{left: 0, right: 0}, //todo: figure out a sane value for these + value: "!".to_string(), + } + } + ) +} + + #[derive(Clone, PartialEq, Eq, Hash)] pub struct Span { pub left: usize, @@ -13,12 +63,28 @@ pub struct Spanned { pub value: T, } + #[derive(Clone, PartialEq, Eq, Hash)] -pub struct TypeUsage { - pub name: Spanned, - pub ty: types::SpecifiedType, - //TODO: Generics go here - // mut, weak here +pub struct FunctionTypeUsage { + pub arguments: Vec, + pub return_type: TypeUsage, +} + +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct NamedTypeUsage { + name: Identifier, +} + +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct UnknownTypeUsage { + name: String, +} + +#[derive(Clone, PartialEq, Eq, Hash)] +pub enum TypeUsage { + Function(FunctionTypeUsage), + Named(NamedTypeUsage), + Unknown(UnknownTypeUsage), } #[derive(Clone, PartialEq, Eq, Hash)] @@ -31,70 +97,158 @@ pub enum Operator { #[derive(Clone, PartialEq, Eq, Hash)] pub struct LiteralInt { - pub value: i64, + pub value: Spanned, + pub type: TypeUsage, +} + +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct LiteralFloat { + pub value: Spanned, + pub type: TypeUsage, +} + +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct LiteralStruct { + pub fields: HashMap, + pub type: TypeUsage, } #[derive(Clone, PartialEq, Eq, Hash)] pub struct Identifier { - pub name: String, + pub name: Spanned, } #[derive(Clone, PartialEq, Eq, Hash)] pub struct FunctionCall { - pub name: Spanned, - pub arguments: Vec>>, + pub source: Expression, + pub arguments: Vec, + pub type: TypeUsage, +} + +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct StructGetter { + pub source: Box, + pub attribute: Identifier, + pub type: TypeUsage, } #[derive(Clone, PartialEq, Eq, Hash)] pub struct Operation { - pub left: Spanned>, + pub left: Expression, pub op: Operator, - pub right: Spanned>, + pub right: Expression, + pub type: TypeUsage, } #[derive(Clone, PartialEq, Eq, Hash)] -pub enum Expression { - LiteralInt(Spanned), - FunctionCall(Spanned), - Identifier(Spanned), +pub struct VariableUsage { + pub name: Identifier, + pub type: TypeUsage, +} + +#[derive(Clone, PartialEq, Eq, Hash)] +pub enum Subexpression { + LiteralInt(LiteralInt), + FunctionCall(FunctionCall), + Identifier(Identifier), Op(Operation), } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct Assignment { - pub name: Spanned, - pub type_usage: Option>, - // mut, weak here if type not used - pub expression: Spanned>, +pub struct Expression { + pub subexpression: Spanned>, + pub type: TypeUsage, +} + +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct ReturnStatement { + pub source: Expression, + pub type: TypeUsage, +} + +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct LetStatement { + variable_name: Identifier, + type: VariableUsage, + expression: Expression, +} + +pub enum AssignmentTarget { + Variable(VariableUsage), + StructAttr(StructGetter), +} + +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct AssignmentStatement { + pub source: AssignmentTarget, + pub expression: Expression, + pub type: TypeUsage, } #[derive(Clone, PartialEq, Eq, Hash)] pub enum Statement { - Assignment(Spanned), - Expression(Spanned>), + Assignment(Assignment), + Expression(Expression), } #[derive(Clone, PartialEq, Eq, Hash)] pub struct Block { pub statements: Vec>, + pub type: TypeUsage, } #[derive(Clone, PartialEq, Eq, Hash)] pub struct VariableDeclaration { - pub name: Spanned, - pub type_usage: Spanned, + pub name: Identifier, + pub type: TypeUsage, +} + +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct FunctionDeclaration { + pub name: Identifier, + pub arguments: Vec, + pub return_type: TypeUsage, } #[derive(Clone, PartialEq, Eq, Hash)] pub struct Function { - pub name: Spanned, - pub arguments: Vec, - pub return_type: Spanned, + pub declaration: FunctionDeclaration, pub block: Block, } +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct PrimitiveTypeDeclaration { + pub name: String, // cannot be identifier as it's not declared anywhere specific, it's builtins +} + +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct StructTypeDeclaration { + pub name: Identifier, + pub fields: HashMap, +} + +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct AliasTypeDeclaration { + pub name: Identifier, + pub replaces: TypeUsage, +} + +#[derive(Clone, PartialEq, Eq, Hash)] +pub enum TypeDeclaration { + Struct(StructTypeDeclaration), + Primitive(PrimitiveTypeDeclaration), + Alias(AliasTypeDeclaration), +} + +#[derive(Clone, PartialEq, Eq, Hash)] +pub enum Impl { + pub struct_name: Identifier, + pub functions: Vec, +} #[derive(Clone, PartialEq, Eq, Hash)] pub struct Module { pub functions: Vec, + pub types: Vec, + pub impls: Vec, } diff --git a/src/grammar.lalrpop b/src/grammar.lalrpop index 7837aa9..1207f13 100644 --- a/src/grammar.lalrpop +++ b/src/grammar.lalrpop @@ -2,11 +2,30 @@ use std::str::FromStr; use crate::ast; use crate::types; -grammar; +grammar(id_generator: ast::IdGenerator); -pub LiteralInt: ast::LiteralInt = { - => ast::LiteralInt{value: i64::from_str(literal).unwrap()} +pub TypeUsage: ast::TypeUsage = { + "fn" "(" > ")" => ast::TypeUsage::Function(ast::FunctionTypeUsage{arguments: args, return_type: ast::new_unit()}), + "fn" "(" > ")" ":" => ast::TypeUsage::Function(ast::FunctionTypeUsage{arguments: args, return_type: return_type), + => ast::TypeUsage::Named(ast::NamedTypeUsage{name: name}) +}; + + +pub LiteralInt: i64 = { + => i64::from_str(literal).unwrap() +}; + +pub SpannedLiteralInt: ast::LiteralInt { + > => ast::LiteralInt{value: literal_int, type: ast::new_named("i64")}, +}; + +pub LiteralFloat: f64 = { + => f64::from_str(literal).unwrap() +}; + +pub SpannedLiteralInt: ast::LiteralFloat { + > => ast::LiteralFloat{value: literal_float, type: ast::new_named("f64")}, }; pub Identifier: ast::Identifier = {