diff --git a/src/builtins/mod.rs b/src/builtins/mod.rs index 0402004..f5bee3a 100644 --- a/src/builtins/mod.rs +++ b/src/builtins/mod.rs @@ -10,5 +10,18 @@ pub fn initialise_globals() -> GlobalNamespace { ns.register_type("integer").unwrap().add_trait(&numeric); ns.register_type("float").unwrap().add_trait(&numeric); + ns.register_type("string").unwrap(); + + // def math add [ Numeric Numeric ] -> Numeric + ns.register_command( + "add", + Some(TypeDef::List(vec![ + TypeDef::Trait(numeric), + TypeDef::Trait(numeric), + ])), + Some(TypeDef::Trait(numeric)), + ) + .unwrap(); + ns } diff --git a/src/builtins/namespace.rs b/src/builtins/namespace.rs index 1249cf9..26a6af3 100644 --- a/src/builtins/namespace.rs +++ b/src/builtins/namespace.rs @@ -101,6 +101,28 @@ impl GlobalNamespace { } } + pub fn get_type(&self, id: usize) -> Option { + if self.types.borrow().len() > id { + Some(Type { + id, + namespace: self, + }) + } else { + None + } + } + + pub fn get_trait(&self, id: usize) -> Option { + if self.traits.borrow().len() > id { + Some(Trait { + id, + namespace: self, + }) + } else { + None + } + } + pub fn get_type_by_name(&self, name: &str) -> Option { if let Some(TypeNamespaceId::Types(id)) = self.type_namespace.borrow().get(name) { Some(Type { @@ -129,6 +151,7 @@ pub enum TypeRegistrationError { NameAlreadyExists, } +#[derive(Clone, Copy)] pub struct Type<'a> { id: usize, namespace: &'a GlobalNamespace, @@ -158,6 +181,7 @@ struct InternalType { name: String, } +#[derive(Clone, Copy)] pub struct Trait<'a> { id: usize, namespace: &'a GlobalNamespace, @@ -169,11 +193,29 @@ struct InternalTrait { name: String, } -struct Command<'a> { +#[derive(Clone, Copy)] +pub struct Command<'a> { id: usize, namespace: &'a GlobalNamespace, } +impl<'a> Command<'a> { + pub fn get_input_types(&self) -> Option> { + self.namespace + .commands + .borrow() + .get(self.id) + .unwrap() + .input + .map(|def| TypeDef::from_internal(self.namespace, &def)) + } + pub fn get_output_types(&self) -> Option { + self.namespace.commands.borrow()[self.id] + .output + .map(|def| TypeDef::from_internal(self.namespace, &def)) + } +} + struct InternalCommand { name: String, // gosh this is hacky @@ -193,6 +235,28 @@ pub enum TypeDef<'a> { Record(Vec<(String, TypeDef<'a>)>), } +impl<'a> TypeDef<'a> { + fn from_internal(ns: &'a GlobalNamespace, def: &'a InternalTypeDef) -> TypeDef<'a> { + match def { + InternalTypeDef::Single(id) => match id { + // safe to unwrap because this is only used with internal representations + TypeNamespaceId::Types(id) => TypeDef::Type(ns.get_type(*id).unwrap()), + TypeNamespaceId::Traits(id) => TypeDef::Trait(ns.get_trait(*id).unwrap()), + }, + InternalTypeDef::List(list) => TypeDef::List( + list.into_iter() + .map(|def| Self::from_internal(ns, def)) + .collect(), + ), + InternalTypeDef::Record(rec) => TypeDef::Record( + rec.into_iter() + .map(|(name, def)| (name.clone(), Self::from_internal(ns, def))) + .collect(), + ), + } + } +} + enum InternalTypeDef { Single(TypeNamespaceId), List(Vec), diff --git a/src/lexer.rs b/src/lexer.rs index 831a1c4..9db137c 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -7,7 +7,7 @@ pub enum Token<'a> { Word(&'a str), #[regex("[\\d]+", priority = 2, callback = |lex| lex.slice().parse::().unwrap())] IntLiteral(i64), - #[regex("[\\d]+.[\\d]+", |lex| lex.slice().parse::().unwrap())] + #[regex("[\\d]+\\.[\\d]+", |lex| lex.slice().parse::().unwrap())] FloatLiteral(f64), #[regex(r#""([^"\\]|\\["\\bnfrt]|u[a-fA-F0-9]{4})*""#, |lex| lex.slice().to_owned())] StringLiteral(String), diff --git a/src/main.rs b/src/main.rs index 7955b8f..467130e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,16 +1,19 @@ use builtins::initialise_globals; -use codespan_reporting::files::SimpleFiles; -use codespan_reporting::term; -use codespan_reporting::term::termcolor::ColorChoice; -use codespan_reporting::term::termcolor::StandardStream; +use codespan_reporting::{ + files::SimpleFiles, + term::{ + self, + termcolor::{ColorChoice, StandardStream}, + }, +}; use syntax::parse_syntax; use crate::syntax::check::check; mod builtins; -mod hir; mod lexer; mod syntax; +mod type_repr; fn main() { let mut files = SimpleFiles::new(); @@ -57,7 +60,24 @@ fn main() { out_errs.append(&mut errs) } - // invalid + let valid_add_input_pipe = "1 | add 2"; + let valid_add_input_pipe_id = files.add("valid_add_input_pipe", valid_add_input_pipe); + let syntax = dbg!(check( + parse_syntax(valid_add_input_pipe, valid_add_input_pipe_id).unwrap(), + valid_add_input_pipe, + valid_add_input_pipe_id, + ) + .unwrap()); + + let valid_add_input_args = "add 1 2"; + let valid_add_input_args_id = files.add("valid_add_input_args", valid_add_input_args); + let syntax = dbg!(check( + parse_syntax(valid_add_input_args, valid_add_input_args_id).unwrap(), + valid_add_input_args, + valid_add_input_args_id, + ) + .unwrap()); + let writer = StandardStream::stderr(ColorChoice::Always); let config = term::Config::default(); diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs index df3c971..eec82fc 100644 --- a/src/syntax/mod.rs +++ b/src/syntax/mod.rs @@ -13,8 +13,8 @@ mod error; #[derive(Debug, Clone, PartialEq)] pub struct PipelineElement { - kind: PipelineElementKind, - span: Span, + pub kind: PipelineElementKind, + pub span: Span, } #[derive(Debug, Clone, PartialEq)] @@ -25,8 +25,8 @@ pub enum PipelineElementKind { #[derive(Debug, Clone, PartialEq)] pub struct CommandPart { - kind: CommandPartKind, - span: Span, + pub kind: CommandPartKind, + pub span: Span, } #[derive(Debug, Clone, PartialEq)]