BRANCHING (TURING COMPLETE????)
This commit is contained in:
@@ -11,7 +11,8 @@ impl RV64Instruction {
|
||||
pub fn parse(inst: &PInstruction, ctx: &mut FnLowerCtx) -> Option<Self> {
|
||||
let args = &inst.args[..];
|
||||
let opstr = &**inst.op.inner.as_ref()?;
|
||||
let opi = |ctx: &mut FnLowerCtx<'_, '_>, op: Funct3| -> Option<Self> {
|
||||
// TODO: surely this can be abstracted...
|
||||
let opi = |ctx: &mut FnLowerCtx<'_>, op: Funct3| -> Option<Self> {
|
||||
let [dest, src, imm] = args else {
|
||||
ctx.err(format!("{opstr} requires 3 arguments"));
|
||||
return None;
|
||||
@@ -21,7 +22,7 @@ impl RV64Instruction {
|
||||
let imm = i32_from_arg(imm, ctx)?;
|
||||
Some(Self::OpImm { op, dest, src, imm })
|
||||
};
|
||||
let op = |ctx: &mut FnLowerCtx<'_, '_>, op: Funct3, funct: Funct7| -> Option<Self> {
|
||||
let op = |ctx: &mut FnLowerCtx<'_>, op: Funct3, funct: Funct7| -> Option<Self> {
|
||||
let [dest, src1, src2] = args else {
|
||||
ctx.err(format!("{opstr} requires 3 arguments"));
|
||||
return None;
|
||||
@@ -37,7 +38,7 @@ impl RV64Instruction {
|
||||
src2,
|
||||
})
|
||||
};
|
||||
let opif7 = |ctx: &mut FnLowerCtx<'_, '_>, op: Funct3, funct: Funct7| -> Option<Self> {
|
||||
let opif7 = |ctx: &mut FnLowerCtx<'_>, op: Funct3, funct: Funct7| -> Option<Self> {
|
||||
let [dest, src, imm] = args else {
|
||||
ctx.err(format!("{opstr} requires 3 arguments"));
|
||||
return None;
|
||||
@@ -53,7 +54,7 @@ impl RV64Instruction {
|
||||
imm,
|
||||
})
|
||||
};
|
||||
let store = |ctx: &mut FnLowerCtx<'_, '_>, width: Funct3| -> Option<Self> {
|
||||
let store = |ctx: &mut FnLowerCtx<'_>, width: Funct3| -> Option<Self> {
|
||||
let [src, offset, base] = args else {
|
||||
ctx.err(format!("{opstr} requires 3 arguments"));
|
||||
return None;
|
||||
@@ -68,7 +69,7 @@ impl RV64Instruction {
|
||||
base,
|
||||
})
|
||||
};
|
||||
let load = |ctx: &mut FnLowerCtx<'_, '_>, width: Funct3| -> Option<Self> {
|
||||
let load = |ctx: &mut FnLowerCtx<'_>, width: Funct3| -> Option<Self> {
|
||||
let [dest, offset, base] = args else {
|
||||
ctx.err(format!("{opstr} requires 3 arguments"));
|
||||
return None;
|
||||
|
||||
@@ -5,11 +5,13 @@ use super::{FnLowerCtx, FnLowerable, PBlock, PStatement};
|
||||
impl FnLowerable for PBlock {
|
||||
type Output = VarInst;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<VarInst> {
|
||||
let ctx = &mut ctx.sub();
|
||||
ctx.program.push();
|
||||
for statement in &self.statements {
|
||||
statement.lower(ctx);
|
||||
}
|
||||
self.result.as_ref()?.lower(ctx)
|
||||
let res = self.result.as_ref().map(|r| r.lower(ctx)).flatten();
|
||||
ctx.program.pop();
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,10 +20,10 @@ impl FnLowerable for PStatement {
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<VarInst> {
|
||||
match self {
|
||||
super::PStatement::Let(def, e) => {
|
||||
let def = def.lower(ctx.map, ctx.output)?;
|
||||
let def = def.lower(ctx.program, ctx.output)?;
|
||||
let res = e.lower(ctx);
|
||||
if let Some(res) = res {
|
||||
ctx.map.name_var(&def, res.id);
|
||||
ctx.program.name_var(&def, res.id);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
use crate::ir::{NamespaceGuard, Origin, Type, VarDef};
|
||||
use crate::ir::{IRUProgram, Origin, Type, VarDef};
|
||||
|
||||
use super::{CompilerMsg, CompilerOutput, FileSpan, Node, PType, PVarDef};
|
||||
|
||||
impl Node<PVarDef> {
|
||||
pub fn lower(
|
||||
&self,
|
||||
namespace: &mut NamespaceGuard,
|
||||
program: &mut IRUProgram,
|
||||
output: &mut CompilerOutput,
|
||||
) -> Option<VarDef> {
|
||||
let s = self.as_ref()?;
|
||||
let name = s.name.as_ref()?.to_string();
|
||||
let ty = match &s.ty {
|
||||
Some(ty) => ty.lower(namespace, output),
|
||||
Some(ty) => ty.lower(program, output),
|
||||
None => Type::Infer,
|
||||
};
|
||||
Some(VarDef {
|
||||
@@ -23,7 +23,7 @@ impl Node<PVarDef> {
|
||||
}
|
||||
|
||||
impl Node<PType> {
|
||||
pub fn lower(&self, namespace: &mut NamespaceGuard, output: &mut CompilerOutput) -> Type {
|
||||
pub fn lower(&self, namespace: &mut IRUProgram, output: &mut CompilerOutput) -> Type {
|
||||
self.as_ref()
|
||||
.map(|t| t.lower(namespace, output, self.span))
|
||||
.unwrap_or(Type::Error)
|
||||
@@ -33,7 +33,7 @@ impl Node<PType> {
|
||||
impl PType {
|
||||
pub fn lower(
|
||||
&self,
|
||||
namespace: &mut NamespaceGuard,
|
||||
namespace: &mut IRUProgram,
|
||||
output: &mut CompilerOutput,
|
||||
span: FileSpan,
|
||||
) -> Type {
|
||||
|
||||
@@ -10,9 +10,9 @@ impl FnLowerable for PExpr {
|
||||
Some(match self {
|
||||
PExpr::Lit(l) => match l.as_ref()? {
|
||||
super::PLiteral::String(s) => {
|
||||
let dest = ctx.map.temp_var(l.span, Type::Bits(8).slice());
|
||||
let dest = ctx.program.temp_var(l.span, Type::Bits(8).slice());
|
||||
let data = s.as_bytes().to_vec();
|
||||
let src = ctx.map.def_data(
|
||||
let src = ctx.program.def_data(
|
||||
DataDef {
|
||||
ty: Type::Bits(8).arr(data.len() as u32),
|
||||
origin: Origin::File(l.span),
|
||||
@@ -25,8 +25,8 @@ impl FnLowerable for PExpr {
|
||||
}
|
||||
super::PLiteral::Char(c) => {
|
||||
let ty = Type::Bits(8);
|
||||
let dest = ctx.map.temp_var(l.span, ty.clone());
|
||||
let src = ctx.map.def_data(
|
||||
let dest = ctx.program.temp_var(l.span, ty.clone());
|
||||
let src = ctx.program.def_data(
|
||||
DataDef {
|
||||
ty,
|
||||
origin: Origin::File(l.span),
|
||||
@@ -40,8 +40,8 @@ impl FnLowerable for PExpr {
|
||||
super::PLiteral::Number(n) => {
|
||||
// TODO: temp
|
||||
let ty = Type::Bits(64);
|
||||
let dest = ctx.map.temp_var(l.span, Type::Bits(64));
|
||||
let src = ctx.map.def_data(
|
||||
let dest = ctx.program.temp_var(l.span, Type::Bits(64));
|
||||
let src = ctx.program.def_data(
|
||||
DataDef {
|
||||
ty,
|
||||
origin: Origin::File(l.span),
|
||||
@@ -60,12 +60,15 @@ impl FnLowerable for PExpr {
|
||||
PExpr::BinaryOp(op, e1, e2) => {
|
||||
let res1 = e1.lower(ctx)?;
|
||||
if *op == PInfixOp::Access {
|
||||
let sty = &ctx.map.get_var(res1.id).ty;
|
||||
let sty = &ctx.program.get_var(res1.id).ty;
|
||||
let Type::Concrete(tid) = sty else {
|
||||
ctx.err(format!("Type {:?} has no fields", ctx.map.type_name(sty)));
|
||||
ctx.err(format!(
|
||||
"Type {:?} has no fields",
|
||||
ctx.program.type_name(sty)
|
||||
));
|
||||
return None;
|
||||
};
|
||||
let struc = ctx.map.get_struct(*tid);
|
||||
let struc = ctx.program.get_struct(*tid);
|
||||
let Some(box PExpr::Ident(ident)) = &e2.inner else {
|
||||
ctx.err(format!("Field accesses must be identifiers",));
|
||||
return None;
|
||||
@@ -84,14 +87,29 @@ impl FnLowerable for PExpr {
|
||||
temp
|
||||
} else {
|
||||
let res2 = e2.lower(ctx)?;
|
||||
todo!()
|
||||
match op {
|
||||
PInfixOp::Add => todo!(),
|
||||
PInfixOp::Sub => todo!(),
|
||||
PInfixOp::Mul => todo!(),
|
||||
PInfixOp::Div => todo!(),
|
||||
PInfixOp::LessThan => todo!(),
|
||||
PInfixOp::GreaterThan => todo!(),
|
||||
PInfixOp::Access => todo!(),
|
||||
PInfixOp::Assign => {
|
||||
ctx.push(IRUInstruction::Mv {
|
||||
dest: res1,
|
||||
src: res2,
|
||||
});
|
||||
res1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PExpr::UnaryOp(op, e) => {
|
||||
let res = e.lower(ctx)?;
|
||||
match op {
|
||||
UnaryOp::Ref => {
|
||||
let temp = ctx.temp(ctx.map.get_var(res.id).ty.clone().rf());
|
||||
let temp = ctx.temp(ctx.program.get_var(res.id).ty.clone().rf());
|
||||
ctx.push(IRUInstruction::Ref {
|
||||
dest: temp,
|
||||
src: res,
|
||||
@@ -99,11 +117,11 @@ impl FnLowerable for PExpr {
|
||||
temp
|
||||
}
|
||||
UnaryOp::Deref => {
|
||||
let t = &ctx.map.get_var(res.id).ty;
|
||||
let t = &ctx.program.get_var(res.id).ty;
|
||||
let Type::Ref(inner) = t else {
|
||||
ctx.err(format!(
|
||||
"Cannot dereference type {:?}",
|
||||
ctx.map.type_name(t)
|
||||
ctx.program.type_name(t)
|
||||
));
|
||||
return None;
|
||||
};
|
||||
@@ -124,7 +142,7 @@ impl FnLowerable for PExpr {
|
||||
let arg = arg.lower(ctx)?;
|
||||
nargs.push(arg);
|
||||
}
|
||||
let def = ctx.map.get_fn_var(fe.id);
|
||||
let def = ctx.program.get_fn_var(fe.id);
|
||||
let ty = match def {
|
||||
Some(def) => def.ret.clone(),
|
||||
None => {
|
||||
@@ -132,7 +150,7 @@ impl FnLowerable for PExpr {
|
||||
e.span,
|
||||
format!(
|
||||
"Expected function, found {}",
|
||||
ctx.map.type_name(&ctx.map.get_var(fe.id).ty)
|
||||
ctx.program.type_name(&ctx.program.get_var(fe.id).ty)
|
||||
),
|
||||
);
|
||||
Type::Error
|
||||
@@ -148,6 +166,29 @@ impl FnLowerable for PExpr {
|
||||
}
|
||||
PExpr::Group(e) => e.lower(ctx)?,
|
||||
PExpr::Construct(c) => c.lower(ctx)?,
|
||||
PExpr::If(cond, body) => {
|
||||
let cond = cond.lower(ctx)?;
|
||||
ctx.program.push();
|
||||
let mut body_ctx = ctx.branch();
|
||||
body.lower(&mut body_ctx);
|
||||
let body = body_ctx.instructions;
|
||||
ctx.program.pop();
|
||||
ctx.push(IRUInstruction::If { cond, body });
|
||||
return None;
|
||||
}
|
||||
PExpr::Loop(body) => {
|
||||
ctx.program.push();
|
||||
let mut body_ctx = ctx.branch();
|
||||
body.lower(&mut body_ctx);
|
||||
let body = body_ctx.instructions;
|
||||
ctx.program.pop();
|
||||
ctx.push(IRUInstruction::Loop { body });
|
||||
return None;
|
||||
}
|
||||
PExpr::Break => {
|
||||
ctx.push(IRUInstruction::Break);
|
||||
return None;
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,20 @@
|
||||
use super::{CompilerMsg, CompilerOutput, FileSpan, FnLowerable, Node, PFunction};
|
||||
use crate::{
|
||||
ir::{
|
||||
FnDef, FnID, IRInstructions, IRUFunction, IRUInstruction, Idents, NamespaceGuard, Origin,
|
||||
Type, VarDef, VarInst,
|
||||
FnDef, FnID, IRUFunction, IRUInstrInst, IRUInstruction, IRUProgram, Idents, Origin, Type,
|
||||
VarDef, VarInst,
|
||||
},
|
||||
parser,
|
||||
};
|
||||
|
||||
impl Node<PFunction> {
|
||||
pub fn lower_header(
|
||||
&self,
|
||||
map: &mut NamespaceGuard,
|
||||
output: &mut CompilerOutput,
|
||||
) -> Option<FnID> {
|
||||
pub fn lower_header(&self, map: &mut IRUProgram, output: &mut CompilerOutput) -> Option<FnID> {
|
||||
self.as_ref()?.lower_header(map, output)
|
||||
}
|
||||
pub fn lower_body(
|
||||
&self,
|
||||
id: FnID,
|
||||
map: &mut NamespaceGuard,
|
||||
map: &mut IRUProgram,
|
||||
output: &mut CompilerOutput,
|
||||
) -> Option<IRUFunction> {
|
||||
Some(self.as_ref()?.lower_body(id, map, output))
|
||||
@@ -26,11 +22,7 @@ impl Node<PFunction> {
|
||||
}
|
||||
|
||||
impl PFunction {
|
||||
pub fn lower_header(
|
||||
&self,
|
||||
map: &mut NamespaceGuard,
|
||||
output: &mut CompilerOutput,
|
||||
) -> Option<FnID> {
|
||||
pub fn lower_header(&self, map: &mut IRUProgram, output: &mut CompilerOutput) -> Option<FnID> {
|
||||
let header = self.header.as_ref()?;
|
||||
let name = header.name.as_ref()?;
|
||||
let args = header
|
||||
@@ -58,44 +50,43 @@ impl PFunction {
|
||||
pub fn lower_body(
|
||||
&self,
|
||||
id: FnID,
|
||||
map: &mut NamespaceGuard,
|
||||
map: &mut IRUProgram,
|
||||
output: &mut CompilerOutput,
|
||||
) -> IRUFunction {
|
||||
let mut instructions = IRInstructions::new();
|
||||
let def = map.get_fn(id).clone();
|
||||
let args = def.args.iter().map(|a| map.named_var(a.clone())).collect();
|
||||
let mut ctx = FnLowerCtx {
|
||||
instructions: &mut instructions,
|
||||
map,
|
||||
instructions: Vec::new(),
|
||||
program: map,
|
||||
output,
|
||||
span: self.body.span,
|
||||
};
|
||||
if let Some(src) = self.body.lower(&mut ctx) {
|
||||
instructions.push(IRUInstruction::Ret { src }, src.span);
|
||||
ctx.instructions.push(IRUInstrInst {
|
||||
i: IRUInstruction::Ret { src },
|
||||
span: src.span,
|
||||
});
|
||||
}
|
||||
IRUFunction {
|
||||
name: def.name.clone(),
|
||||
args,
|
||||
ret: def.ret,
|
||||
instructions: ctx.instructions,
|
||||
}
|
||||
IRUFunction::new(def.name.clone(), args, def.ret, instructions)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FnLowerCtx<'a, 'n> {
|
||||
pub map: &'a mut NamespaceGuard<'n>,
|
||||
pub instructions: &'a mut IRInstructions,
|
||||
pub struct FnLowerCtx<'a> {
|
||||
pub program: &'a mut IRUProgram,
|
||||
pub instructions: Vec<IRUInstrInst>,
|
||||
pub output: &'a mut CompilerOutput,
|
||||
pub span: FileSpan,
|
||||
}
|
||||
|
||||
impl<'n> FnLowerCtx<'_, 'n> {
|
||||
pub fn span<'b>(&'b mut self, span: FileSpan) -> FnLowerCtx<'b, 'n> {
|
||||
FnLowerCtx {
|
||||
map: self.map,
|
||||
instructions: self.instructions,
|
||||
output: self.output,
|
||||
span,
|
||||
}
|
||||
}
|
||||
impl FnLowerCtx<'_> {
|
||||
pub fn get(&mut self, node: &Node<parser::PIdent>) -> Option<Idents> {
|
||||
let name = node.inner.as_ref()?;
|
||||
let res = self.map.get(name);
|
||||
let res = self.program.get(name);
|
||||
if res.is_none() {
|
||||
self.err_at(node.span, format!("Identifier '{}' not found", name));
|
||||
}
|
||||
@@ -124,18 +115,18 @@ impl<'n> FnLowerCtx<'_, 'n> {
|
||||
self.output.err(CompilerMsg::from_span(span, msg))
|
||||
}
|
||||
pub fn temp(&mut self, ty: Type) -> VarInst {
|
||||
self.map.temp_var(self.span, ty)
|
||||
self.program.temp_var(self.span, ty)
|
||||
}
|
||||
pub fn push(&mut self, i: IRUInstruction) {
|
||||
self.instructions.push(i, self.span);
|
||||
self.instructions.push(IRUInstrInst { i, span: self.span });
|
||||
}
|
||||
pub fn push_at(&mut self, i: IRUInstruction, span: FileSpan) {
|
||||
self.instructions.push(i, span);
|
||||
self.instructions.push(IRUInstrInst { i, span });
|
||||
}
|
||||
pub fn sub<'b>(&'b mut self) -> FnLowerCtx<'b, 'n> {
|
||||
pub fn branch<'a>(&'a mut self) -> FnLowerCtx<'a> {
|
||||
FnLowerCtx {
|
||||
map: self.map,
|
||||
instructions: self.instructions,
|
||||
program: self.program,
|
||||
instructions: Vec::new(),
|
||||
output: self.output,
|
||||
span: self.span,
|
||||
}
|
||||
|
||||
@@ -19,7 +19,11 @@ pub trait FnLowerable {
|
||||
impl<T: FnLowerable> FnLowerable for Node<T> {
|
||||
type Output = T::Output;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<T::Output> {
|
||||
self.as_ref()?.lower(&mut ctx.span(self.span))
|
||||
let old_span = ctx.span;
|
||||
ctx.span = self.span;
|
||||
let res = self.as_ref()?.lower(ctx);
|
||||
ctx.span = old_span;
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
use crate::ir::NamespaceGuard;
|
||||
use crate::ir::IRUProgram;
|
||||
|
||||
use super::{PModule, CompilerOutput};
|
||||
|
||||
impl PModule {
|
||||
pub fn lower(&self, map: &mut NamespaceGuard, output: &mut CompilerOutput) {
|
||||
pub fn lower(&self, p: &mut IRUProgram, output: &mut CompilerOutput) {
|
||||
for s in &self.structs {
|
||||
s.lower(map, output);
|
||||
s.lower(p, output);
|
||||
}
|
||||
let mut fns = Vec::new();
|
||||
for f in &self.functions {
|
||||
if let Some(id) = f.lower_header(map, output) {
|
||||
if let Some(id) = f.lower_header(p, output) {
|
||||
fns.push(Some(id));
|
||||
} else {
|
||||
fns.push(None)
|
||||
@@ -17,8 +17,8 @@ impl PModule {
|
||||
}
|
||||
for (f, id) in self.functions.iter().zip(fns) {
|
||||
if let Some(id) = id {
|
||||
if let Some(res) = f.lower_body(id, map, output) {
|
||||
map.write_fn(id, res);
|
||||
if let Some(res) = f.lower_body(id, p, output) {
|
||||
p.write_fn(id, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
common::{CompilerMsg, CompilerOutput, FileSpan},
|
||||
ir::{IRUInstruction, NamespaceGuard, Origin, StructDef, StructField, VarInst},
|
||||
ir::{IRUInstruction, IRUProgram, Origin, StructDef, StructField, VarInst},
|
||||
parser::{Node, PConstruct, PConstructFields, PStruct, PStructFields},
|
||||
};
|
||||
|
||||
@@ -11,7 +11,7 @@ use super::{FnLowerCtx, FnLowerable};
|
||||
impl FnLowerable for PConstruct {
|
||||
type Output = VarInst;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<VarInst> {
|
||||
let ty = self.name.lower(ctx.map, ctx.output);
|
||||
let ty = self.name.lower(ctx.program, ctx.output);
|
||||
let fields = match &self.fields {
|
||||
PConstructFields::Named(nodes) => nodes
|
||||
.iter()
|
||||
@@ -41,7 +41,7 @@ impl FnLowerable for PConstruct {
|
||||
impl PStruct {
|
||||
pub fn lower(
|
||||
&self,
|
||||
map: &mut NamespaceGuard,
|
||||
p: &mut IRUProgram,
|
||||
output: &mut CompilerOutput,
|
||||
span: FileSpan,
|
||||
) -> Option<()> {
|
||||
@@ -53,10 +53,10 @@ impl PStruct {
|
||||
let def = n.as_ref()?;
|
||||
let name = def.name.as_ref()?.to_string();
|
||||
let tynode = def.ty.as_ref()?;
|
||||
let ty = tynode.lower(map, output);
|
||||
let size = map.size_of_type(&ty).unwrap_or_else(|| {
|
||||
let ty = tynode.lower(p, output);
|
||||
let size = p.size_of_type(&ty).unwrap_or_else(|| {
|
||||
output.err(CompilerMsg {
|
||||
msg: format!("Size of type '{}' unknown", map.type_name(&ty)),
|
||||
msg: format!("Size of type '{}' unknown", p.type_name(&ty)),
|
||||
spans: vec![tynode.span],
|
||||
});
|
||||
0
|
||||
@@ -70,8 +70,8 @@ impl PStruct {
|
||||
.iter()
|
||||
.enumerate()
|
||||
.flat_map(|(i, n)| {
|
||||
let ty = n.as_ref()?.lower(map, output, span);
|
||||
let size = map.size_of_type(&ty)?;
|
||||
let ty = n.as_ref()?.lower(p, output, span);
|
||||
let size = p.size_of_type(&ty)?;
|
||||
let res = Some((format!("{i}"), StructField { ty, offset }));
|
||||
offset += size;
|
||||
res
|
||||
@@ -79,7 +79,7 @@ impl PStruct {
|
||||
.collect(),
|
||||
PStructFields::None => HashMap::new(),
|
||||
};
|
||||
map.def_type(StructDef {
|
||||
p.def_type(StructDef {
|
||||
name: self.name.as_ref()?.to_string(),
|
||||
origin: Origin::File(span),
|
||||
size: offset,
|
||||
@@ -90,7 +90,7 @@ impl PStruct {
|
||||
}
|
||||
|
||||
impl Node<PStruct> {
|
||||
pub fn lower(&self, map: &mut NamespaceGuard, output: &mut CompilerOutput) {
|
||||
self.as_ref().map(|i| i.lower(map, output, self.span));
|
||||
pub fn lower(&self, p: &mut IRUProgram, output: &mut CompilerOutput) {
|
||||
self.as_ref().map(|i| i.lower(p, output, self.span));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use super::{Node, PIdent, Parsable, ParseResult, ParserCtx, Symbol, CompilerMsg};
|
||||
use super::{CompilerMsg, Node, PIdent, Parsable, ParseResult, ParserCtx, Symbol};
|
||||
|
||||
pub struct PInstruction {
|
||||
pub op: Node<PIdent>,
|
||||
@@ -36,7 +36,19 @@ impl Parsable for PAsmArg {
|
||||
return ParseResult::Ok(Self::Value(ident));
|
||||
}
|
||||
|
||||
let next = ctx.expect_peek()?;
|
||||
let mut next = ctx.expect_peek()?;
|
||||
if next.is_symbol(Symbol::Minus) {
|
||||
ctx.next();
|
||||
if let Some(mut ident) = ctx.maybe_parse::<PIdent>() {
|
||||
// TODO: this is so messed up
|
||||
if let Some(i) = ident.as_mut() {
|
||||
i.0.insert(0, '-')
|
||||
}
|
||||
return ParseResult::Ok(Self::Value(ident));
|
||||
}
|
||||
next = ctx.expect_peek()?;
|
||||
}
|
||||
|
||||
if !next.is_symbol(Symbol::OpenCurly) {
|
||||
return ParseResult::Err(CompilerMsg::unexpected_token(
|
||||
next,
|
||||
|
||||
@@ -19,6 +19,9 @@ pub enum PExpr {
|
||||
Group(BoxNode),
|
||||
AsmBlock(Node<PAsmBlock>),
|
||||
Construct(Node<PConstruct>),
|
||||
If(BoxNode, BoxNode),
|
||||
Loop(BoxNode),
|
||||
Break,
|
||||
}
|
||||
|
||||
impl Parsable for PExpr {
|
||||
@@ -42,6 +45,18 @@ impl Parsable for PExpr {
|
||||
Self::Group(res.node.bx())
|
||||
} else if next.is_symbol(Symbol::OpenCurly) {
|
||||
Self::Block(PBlock::parse_node(ctx)?)
|
||||
} else if next.is_keyword(Keyword::If) {
|
||||
ctx.next();
|
||||
let cond = ctx.parse()?.bx();
|
||||
let body = ctx.parse()?.bx();
|
||||
Self::If(cond, body)
|
||||
} else if next.is_keyword(Keyword::Loop) {
|
||||
ctx.next();
|
||||
let body = ctx.parse()?.bx();
|
||||
Self::Loop(body)
|
||||
} else if next.is_keyword(Keyword::Break) {
|
||||
ctx.next();
|
||||
Self::Break
|
||||
} else if next.is_keyword(Keyword::Asm) {
|
||||
ctx.next();
|
||||
Self::AsmBlock(ctx.parse()?)
|
||||
@@ -143,14 +158,13 @@ impl Debug for PExpr {
|
||||
}
|
||||
f.write_char(')')?;
|
||||
}
|
||||
PExpr::UnaryOp(op, e) => {
|
||||
write!(f, "(")?;
|
||||
write!(f, "{}", op.str())?;
|
||||
write!(f, "{:?})", *e)?;
|
||||
}
|
||||
PExpr::UnaryOp(op, e) => write!(f, "({}{:?})", op.str(), e)?,
|
||||
PExpr::Group(inner) => inner.fmt(f)?,
|
||||
PExpr::AsmBlock(inner) => inner.fmt(f)?,
|
||||
PExpr::Construct(inner) => inner.fmt(f)?,
|
||||
PExpr::If(cond, res) => write!(f, "if {cond:?} then {res:?}")?,
|
||||
PExpr::Loop(res) => write!(f, "loop -> {res:?}")?,
|
||||
PExpr::Break => write!(f, "break")?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ impl MaybeParsable for PLiteral {
|
||||
if !first.is_ascii_digit() {
|
||||
return Ok(None);
|
||||
}
|
||||
let (whole, ty) = parse_whole_num(&text);
|
||||
let (whole, ty) = parse_whole_num(text);
|
||||
let mut num = PNumber {
|
||||
whole,
|
||||
decimal: None,
|
||||
|
||||
@@ -4,6 +4,8 @@ pub enum Keyword {
|
||||
Let,
|
||||
If,
|
||||
Return,
|
||||
Break,
|
||||
Loop,
|
||||
Struct,
|
||||
Trait,
|
||||
Impl,
|
||||
@@ -21,6 +23,8 @@ impl Keyword {
|
||||
"if" => Self::If,
|
||||
"for" => Self::For,
|
||||
"return" => Self::Return,
|
||||
"break" => Self::Break,
|
||||
"loop" => Self::Loop,
|
||||
"trait" => Self::Trait,
|
||||
"impl" => Self::Impl,
|
||||
"asm" => Self::Asm,
|
||||
|
||||
Reference in New Issue
Block a user