beginnings of a type system

This commit is contained in:
tezlm 2023-05-09 14:32:19 -07:00
parent 6c02fa4438
commit 924e7e2781
Signed by: tezlm
GPG key ID: 649733FCD94AFBBA
4 changed files with 110 additions and 8 deletions

View file

@ -64,7 +64,7 @@ pub enum UnaryOperation {
pub struct Compiler {
code: Vec<Instruction>,
data: Vec<Data>,
register: Register,
registers: [bool; 256],
}
impl Compiler {
@ -142,9 +142,15 @@ impl Compiler {
}
fn next_register(&mut self) -> Register {
let r = self.register;
self.register += 1;
r
let index = self.registers.iter()
.position(|b| *b == false)
.expect("ran out of registers");
self.registers[index] = true;
index as u8
}
fn free_register(&mut self, reg: Register) {
self.registers[reg as usize] = false;
}
fn push_data(&mut self, data: Data) -> u8 {
@ -158,7 +164,7 @@ pub fn expr(tree: &parser::Tree) -> Bytecode {
let mut compiler = Compiler {
code: Vec::new(),
data: Vec::new(),
register: 0,
registers: [false; 256],
};
let reg = compiler.tree(tree);
let mut bytecode = Bytecode {

View file

@ -10,6 +10,7 @@ mod compiler;
mod runner;
use runner::Value;
use parser::Kind;
fn test(code: &str) -> Value {
let tokens = lexer::lex(code);
@ -17,13 +18,24 @@ fn test(code: &str) -> Value {
.iter()
.filter(|(t, _)| *t != lexer::TokenType::Space)
.collect();
let tree = parser::parse(&mut tokens.iter().peekable(), 0);
let tree = parser::expr(&mut tokens.iter().peekable(), 0);
let bytecode = compiler::expr(&tree);
let result = runner::execute(&bytecode);
dbg!(&result);
result
}
fn parse_kind(code: &str) -> Kind {
let tokens = lexer::lex(code);
let tokens: Vec<_> = tokens
.iter()
.filter(|(t, _)| *t != lexer::TokenType::Space)
.collect();
let tree = parser::kind(&mut tokens.iter().peekable());
dbg!(&tree);
tree
}
fn main() {
// test("math.sin");
// test("math.sin(10 * math.pi)");
@ -37,7 +49,9 @@ fn main() {
#[cfg(test)]
mod tests {
use super::{Value, test};
use std::collections::HashMap;
use super::{Value, Kind, test, parse_kind};
#[test]
fn test_number() {
@ -93,4 +107,40 @@ mod tests {
fn test_let() {
// test("let foo = 123");
}
#[test]
fn test_kind() {
assert_eq!(parse_kind("u8"), Kind::Primitive);
}
#[test]
fn test_kind_struct() {
let k = Kind::Struct(HashMap::from([
("foo".to_owned(), Kind::Primitive),
("bar".to_owned(), Kind::Primitive),
]));
assert_eq!(parse_kind("struct { foo: u8, bar: u8 }"), k);
}
#[test]
fn test_kind_struct_trailing_comma() {
let k = Kind::Struct(HashMap::from([
("foo".to_owned(), Kind::Primitive),
("bar".to_owned(), Kind::Primitive),
]));
assert_eq!(parse_kind("struct { foo: u8, bar: u8, }"), k);
}
#[test]
fn test_kind_struct_nested() {
let k = Kind::Struct(HashMap::from([
("foo".to_owned(), Kind::Primitive),
("bar".to_owned(), Kind::Primitive),
("baz".to_owned(), Kind::Struct(HashMap::from([
("one".to_owned(), Kind::Primitive),
("two".to_owned(), Kind::Primitive),
]))),
]));
assert_eq!(parse_kind("struct { foo: u8, bar: u8, baz: struct { one: u8, two: u8 } }"), k);
}
}

41
src/parser/kind.rs Normal file
View file

@ -0,0 +1,41 @@
use std::collections::HashMap;
use crate::lexer;
#[derive(Debug, PartialEq, Eq)]
pub enum Kind {
Primitive,
Struct(HashMap<String, Kind>),
}
pub fn parse(tokens: &mut std::iter::Peekable<std::slice::Iter<&(lexer::TokenType, &str)>>) -> Kind {
match tokens.next().expect("missing token") {
(_, "u8") => Kind::Primitive,
(_, "struct") => {
let mut kv = HashMap::new();
let (lexer::TokenType::Paran, "{") = tokens.next().expect("missing token") else {
panic!("expected {{");
};
loop {
let (lexer::TokenType::Ident, name) = tokens.peek().expect("missing token") else {
break;
};
tokens.next();
let (lexer::TokenType::Symbol, ":") = tokens.next().expect("missing token") else {
panic!("expected colon");
};
let kind = parse(tokens);
kv.insert(name.to_string(), kind);
let (lexer::TokenType::Symbol, ",") = tokens.peek().expect("missing token") else {
break;
};
tokens.next();
};
let (lexer::TokenType::Paran, "}") = tokens.next().expect("missing token") else {
panic!("expected }}");
};
Kind::Struct(kv)
},
_ => todo!(),
}
}

View file

@ -1,6 +1,11 @@
mod expr;
mod kind;
pub use expr::{
UnaryOpType, BinaryOpType, TernaryOpType,
parse, Tree, ParserError,
parse as expr, Tree, ParserError,
};
pub use kind::{
parse as kind, Kind,
};