diff --git a/src/builtins/mod.rs b/src/builtins/mod.rs index c5abd79..375905d 100644 --- a/src/builtins/mod.rs +++ b/src/builtins/mod.rs @@ -1,18 +1,26 @@ use crate::namespace::{typedef::TypeDef, GlobalNamespace}; +pub const TYPE_INTEGER: &str = "int"; +pub const TYPE_FLOAT: &str = "float"; +pub const TYPE_STRING: &str = "string"; + +pub const TRAIT_NUMERIC: &str = "Num"; + +pub const CMD_ADD: &str = "add"; + pub fn initialise_globals() -> GlobalNamespace { let ns = GlobalNamespace::init(); - let numeric = ns.register_trait("Numeric").unwrap(); + let numeric = ns.register_trait(TRAIT_NUMERIC).unwrap(); - ns.register_type("integer").unwrap().add_trait(&numeric); - ns.register_type("float").unwrap().add_trait(&numeric); + ns.register_type(TYPE_INTEGER).unwrap().add_trait(&numeric); + ns.register_type(TYPE_FLOAT).unwrap().add_trait(&numeric); - ns.register_type("string").unwrap(); + ns.register_type(TYPE_STRING).unwrap(); // def math add [ Numeric Numeric ] -> Numeric ns.register_command( - "add", + CMD_ADD, Some(TypeDef::List(vec![ TypeDef::Trait(numeric), TypeDef::Trait(numeric), diff --git a/src/main.rs b/src/main.rs index 744fe30..d87a338 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,11 +9,14 @@ use codespan_reporting::{ }; use syntax::{check::check, error::SyntaxError, parse_syntax}; +use crate::{builtins::initialise_globals, typed::into_typed_repr}; + mod args; mod builtins; mod lexer; mod namespace; mod syntax; +mod typed; fn main() { let args = Args::parse(); @@ -42,7 +45,7 @@ fn main() { ) .unwrap(); } else { - let check_res = check(&syntax.unwrap()); + let check_res = check(&syntax.clone().unwrap()); if let Err(errs) = check_res { let writer = &mut writer.lock(); @@ -52,6 +55,10 @@ fn main() { for diag in diags { term::emit(writer, &config, &files, &diag).unwrap(); } + } else { + let ns = initialise_globals(); + + println!("typed: {:#?}", into_typed_repr(&ns, syntax.unwrap())); } } } diff --git a/src/typed.rs b/src/typed.rs new file mode 100644 index 0000000..26823e9 --- /dev/null +++ b/src/typed.rs @@ -0,0 +1,108 @@ +use core::panic; + +use crate::{ + builtins::{TYPE_FLOAT, TYPE_INTEGER, TYPE_STRING}, + namespace::{command::Command, r#type::Type, GlobalNamespace}, + syntax::{CommandPart, CommandPartKind, PipelineElement, PipelineElementKind}, +}; + +#[derive(Debug)] +pub struct Expr<'a> { + kind: ExprKind<'a>, + span: logos::Span, +} + +#[derive(Debug)] +pub enum ExprKind<'a> { + Command { + command: Command<'a>, + args: Vec>, + }, + Literal(LiteralKind), +} + +#[derive(Debug)] +pub enum LiteralKind { + Int(i64), + Float(f64), + String(String), +} + +impl LiteralKind { + pub fn get_type<'a>(&self, ns: &'a GlobalNamespace) -> Type<'a> { + match self { + LiteralKind::Int(_) => ns.get_type_by_name(TYPE_INTEGER).unwrap(), + LiteralKind::Float(_) => ns.get_type_by_name(TYPE_FLOAT).unwrap(), + LiteralKind::String(_) => ns.get_type_by_name(TYPE_STRING).unwrap(), + } + } +} + +pub fn into_typed_repr(ns: &GlobalNamespace, syntax: Vec) -> Vec { + let mut res = Vec::new(); + + for item in syntax { + let PipelineElement { kind, span } = item; + match kind { + PipelineElementKind::Command(c) => { + if c.len() == 1 { + let CommandPart { kind, span: _ } = &c[0]; + + res.push(Expr { + kind: match kind { + CommandPartKind::Word(val) => ExprKind::Command { + command: ns.get_command_by_name(val).unwrap(), + args: Vec::new(), + }, + CommandPartKind::Integer(val) => { + ExprKind::Literal(LiteralKind::Int(*val)) + } + CommandPartKind::Float(val) => { + ExprKind::Literal(LiteralKind::Float(*val)) + } + CommandPartKind::String(val) => { + ExprKind::Literal(LiteralKind::String(val.clone())) + } + }, + span, + }) + } else { + let Some(CommandPart { + kind: CommandPartKind::Word(name), + span, + }) = c.first() + else { + panic!("tried conversion to typed representation with invalid syntax") + }; + + res.push(Expr { + kind: ExprKind::Command { + command: ns.get_command_by_name(name).unwrap(), + args: c + .iter() + .skip(1) + .map(|CommandPart { kind, span }| Expr { + kind: ExprKind::Literal(match kind { + CommandPartKind::Word(val) => { + LiteralKind::String(val.to_string()) + } + CommandPartKind::Integer(val) => LiteralKind::Int(*val), + CommandPartKind::Float(val) => LiteralKind::Float(*val), + CommandPartKind::String(val) => { + LiteralKind::String(val.to_string()) + } + }), + span: span.clone(), + }) + .collect(), + }, + span: span.clone(), + }) + } + } + PipelineElementKind::Pipe => {} + } + } + + res +}