forked from katzen-cafe/iowo
implement basic typed representation and conversion to it
This commit is contained in:
parent
75be6e22a0
commit
b50fb5ed06
3 changed files with 129 additions and 6 deletions
|
@ -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),
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
108
src/typed.rs
Normal file
108
src/typed.rs
Normal 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
|
||||
}
|
Loading…
Reference in a new issue