implement basic typed representation and conversion to it

This commit is contained in:
Schrottkatze 2023-11-19 01:44:53 +01:00
parent 75be6e22a0
commit b50fb5ed06
3 changed files with 129 additions and 6 deletions

View file

@ -1,18 +1,26 @@
use crate::namespace::{typedef::TypeDef, GlobalNamespace}; 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 { pub fn initialise_globals() -> GlobalNamespace {
let ns = GlobalNamespace::init(); 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(TYPE_INTEGER).unwrap().add_trait(&numeric);
ns.register_type("float").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 // def math add [ Numeric Numeric ] -> Numeric
ns.register_command( ns.register_command(
"add", CMD_ADD,
Some(TypeDef::List(vec![ Some(TypeDef::List(vec![
TypeDef::Trait(numeric), TypeDef::Trait(numeric),
TypeDef::Trait(numeric), TypeDef::Trait(numeric),

View file

@ -9,11 +9,14 @@ use codespan_reporting::{
}; };
use syntax::{check::check, error::SyntaxError, parse_syntax}; use syntax::{check::check, error::SyntaxError, parse_syntax};
use crate::{builtins::initialise_globals, typed::into_typed_repr};
mod args; mod args;
mod builtins; mod builtins;
mod lexer; mod lexer;
mod namespace; mod namespace;
mod syntax; mod syntax;
mod typed;
fn main() { fn main() {
let args = Args::parse(); let args = Args::parse();
@ -42,7 +45,7 @@ fn main() {
) )
.unwrap(); .unwrap();
} else { } else {
let check_res = check(&syntax.unwrap()); let check_res = check(&syntax.clone().unwrap());
if let Err(errs) = check_res { if let Err(errs) = check_res {
let writer = &mut writer.lock(); let writer = &mut writer.lock();
@ -52,6 +55,10 @@ fn main() {
for diag in diags { for diag in diags {
term::emit(writer, &config, &files, &diag).unwrap(); term::emit(writer, &config, &files, &diag).unwrap();
} }
} else {
let ns = initialise_globals();
println!("typed: {:#?}", into_typed_repr(&ns, syntax.unwrap()));
} }
} }
} }

108
src/typed.rs Normal file
View file

@ -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<Expr<'a>>,
},
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<PipelineElement>) -> Vec<Expr> {
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
}