[fine] Garbage Compile

This commit is contained in:
John Doty 2024-01-08 18:43:47 -08:00
parent 8d09076586
commit 6d2fd446ee
3 changed files with 113 additions and 38 deletions

93
fine/src/compiler.rs Normal file
View file

@ -0,0 +1,93 @@
use crate::{
parser::{Tree, TreeKind, TreeRef},
semantics::{Semantics, Type},
tokens::TokenKind,
};
// TODO: If I were cool this would by actual bytecode.
// But I'm not cool.
pub enum Instruction {
Panic,
PushFloat(f64),
PushString(usize),
PushTrue,
PushFalse,
}
pub struct Function {
instructions: Vec<Instruction>,
strings: Vec<String>,
}
pub fn compile_expression(code: &mut Function, semantics: &Semantics, t: TreeRef) {
let tree = &semantics.tree()[t];
match tree.kind {
TreeKind::Error => code.instructions.push(Instruction::Panic),
TreeKind::LiteralExpression => compile_literal(code, semantics, t, tree),
TreeKind::GroupingExpression => compile_grouping(code, semantics, tree),
TreeKind::UnaryExpression => todo!(),
TreeKind::ConditionalExpression => todo!(),
TreeKind::BinaryExpression => todo!(),
TreeKind::Identifier => todo!(),
TreeKind::CallExpression => todo!(),
TreeKind::Block => todo!(),
_ => {
semantics.internal_compiler_error(Some(t), "tree is not an expression, cannot compile")
}
}
}
fn compile_literal(code: &mut Function, semantics: &Semantics, t: TreeRef, tr: &Tree) {
let Some(tok) = tr.nth_token(0) else {
code.instructions.push(Instruction::Panic);
return;
};
match semantics.type_of(t) {
Type::F64 => code
.instructions
.push(Instruction::PushFloat(tok.as_str().parse().unwrap())),
Type::Bool => code.instructions.push(if tok.kind == TokenKind::True {
Instruction::PushTrue
} else {
Instruction::PushFalse
}),
Type::String => {
let index = code.strings.len();
// TODO: Interpret string here make good!
let mut result = String::new();
let mut input = tok.as_str().chars();
while let Some(ch) = input.next() {
if ch == '\\' {
if let Some(ch) = input.next() {
match ch {
'n' => result.push('\n'),
'r' => result.push('\r'),
't' => result.push('\t'),
_ => result.push(ch),
}
} else {
result.push(ch)
}
} else {
result.push(ch)
}
}
code.strings.push(result);
code.instructions.push(Instruction::PushString(index))
}
Type::Error => code.instructions.push(Instruction::Panic),
_ => panic!("unsupported literal type: {t:?}"),
}
}
fn compile_grouping(code: &mut Function, semantics: &Semantics, t: &Tree) {
if let Some(t) = t.nth_tree(1) {
compile_expression(code, semantics, t)
} else {
code.instructions.push(Instruction::Panic);
}
}
pub fn compile_statement(code: &mut Function, semantics: &Semantics, t: TreeRef) {}