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};
|
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),
|
||||||
|
|
|
@ -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
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