the light is getting closer
This commit is contained in:
@@ -1,14 +1,15 @@
|
||||
use crate::{
|
||||
compiler::arch::riscv::Reg,
|
||||
ir::{
|
||||
arch::riscv64::RV64Instruction, AsmBlockArg, AsmBlockArgType, Type, UInstruction, VarInst
|
||||
arch::riscv64::RV64Instruction, AsmBlockArg, AsmBlockArgType, Type, UInstruction, VarInst,
|
||||
VarInstID,
|
||||
},
|
||||
parser::PAsmBlockArg,
|
||||
};
|
||||
|
||||
use super::{FnLowerCtx, FnLowerable, PAsmBlock, PInstruction, PUAsmBlockArg};
|
||||
|
||||
type PLAsmBlockArg = PAsmBlockArg<Reg, VarInst>;
|
||||
type PLAsmBlockArg = PAsmBlockArg<Reg, VarInstID>;
|
||||
|
||||
impl FnLowerable for PInstruction {
|
||||
type Output = RV64Instruction;
|
||||
@@ -19,7 +20,7 @@ impl FnLowerable for PInstruction {
|
||||
}
|
||||
|
||||
impl FnLowerable for PAsmBlock {
|
||||
type Output = VarInst;
|
||||
type Output = VarInstID;
|
||||
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<Self::Output> {
|
||||
let mut args = Vec::new();
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use crate::{
|
||||
ir::{Type, UInstruction, UVar, VarInst},
|
||||
ir::{Type, UInstruction, UVar, VarInst, VarInstID},
|
||||
parser::{PConstStatement, PStatementLike},
|
||||
};
|
||||
|
||||
use super::{FnLowerCtx, FnLowerable, Import, PBlock, PStatement};
|
||||
|
||||
impl FnLowerable for PBlock {
|
||||
type Output = VarInst;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<VarInst> {
|
||||
type Output = VarInstID;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<VarInstID> {
|
||||
let mut last = None;
|
||||
let mut statements = Vec::new();
|
||||
let mut fn_nodes = Vec::new();
|
||||
|
||||
+36
-31
@@ -1,12 +1,12 @@
|
||||
use super::{func::FnLowerCtx, FnLowerable, PExpr, PostfixOp};
|
||||
use crate::{
|
||||
ir::{Type, UData, UInstruction, VarInst},
|
||||
ir::{Type, UData, UInstruction, VarInst, VarInstID},
|
||||
parser::InfixOp,
|
||||
};
|
||||
|
||||
impl FnLowerable for PExpr {
|
||||
type Output = VarInst;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<VarInst> {
|
||||
type Output = VarInstID;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<VarInstID> {
|
||||
let mut e = self;
|
||||
let mut path = Vec::new();
|
||||
while let PExpr::Member(node, ident) = e {
|
||||
@@ -20,40 +20,40 @@ impl FnLowerable for PExpr {
|
||||
Some(match e {
|
||||
PExpr::Lit(l) => match l {
|
||||
super::PLiteral::String(s) => {
|
||||
let dest = ctx.b.temp_var(ctx.origin, Type::Bits(8).slice(ctx.b.p));
|
||||
let dst = ctx.temp_var(ctx.origin, Type::Bits(8).slice(ctx.p));
|
||||
let data = s.as_bytes().to_vec();
|
||||
let src = ctx.b.def_data(UData {
|
||||
let src = ctx.def_data(UData {
|
||||
name: format!("string \"{}\"", s.replace("\n", "\\n")),
|
||||
ty: Type::Bits(8).arr(ctx.b.p, data.len() as u32),
|
||||
ty: ctx.def_ty(Type::Bits(8).arr(ctx.b.p, data.len() as u32)),
|
||||
content: data,
|
||||
});
|
||||
ctx.push(UInstruction::LoadSlice { dst: dest, src });
|
||||
dest
|
||||
ctx.push(UInstruction::LoadSlice { dst, src });
|
||||
dst
|
||||
}
|
||||
super::PLiteral::Char(c) => {
|
||||
let ty = Type::Bits(8);
|
||||
let dest = ctx.b.temp_var(ctx.origin, ty.clone());
|
||||
let src = ctx.b.def_data(UData {
|
||||
let ty = ctx.def_ty(Type::Bits(8));
|
||||
let dst = ctx.temp_var(ctx.origin, ty.clone());
|
||||
let src = ctx.def_data(UData {
|
||||
name: format!("char '{c}'"),
|
||||
ty,
|
||||
content: c.to_string().as_bytes().to_vec(),
|
||||
});
|
||||
ctx.push(UInstruction::LoadData { dst: dest, src });
|
||||
dest
|
||||
ctx.push(UInstruction::LoadData { dst, src });
|
||||
dst
|
||||
}
|
||||
super::PLiteral::Number(n) => {
|
||||
// TODO: temp
|
||||
let ty = Type::Bits(64);
|
||||
let dest = ctx.b.temp_var(ctx.origin, ty.clone());
|
||||
let src = ctx.b.def_data(UData {
|
||||
let ty = ctx.def_ty(Type::Bits(64));
|
||||
let dst = ctx.temp_var(ctx.origin, ty.clone());
|
||||
let src = ctx.def_data(UData {
|
||||
name: format!("num {n:?}"),
|
||||
ty,
|
||||
content: n.whole.parse::<i64>().unwrap().to_le_bytes().to_vec(),
|
||||
});
|
||||
ctx.push(UInstruction::LoadData { dst: dest, src });
|
||||
dest
|
||||
ctx.push(UInstruction::LoadData { dst, src });
|
||||
dst
|
||||
}
|
||||
super::PLiteral::Unit => ctx.b.temp_var(ctx.origin, Type::Unit),
|
||||
super::PLiteral::Unit => ctx.temp_var(ctx.origin, Type::Unit),
|
||||
},
|
||||
PExpr::Ident(i) => ctx.var(i),
|
||||
PExpr::BinaryOp(op, e1, e2) => match op {
|
||||
@@ -79,14 +79,17 @@ impl FnLowerable for PExpr {
|
||||
PostfixOp::Ref => {
|
||||
let ty = Type::Ref(ctx.b.infer());
|
||||
let dest = ctx.temp(ty);
|
||||
ctx.push(UInstruction::Ref { dst: dest, src: res });
|
||||
ctx.push(UInstruction::Ref {
|
||||
dst: dest,
|
||||
src: res,
|
||||
});
|
||||
dest
|
||||
}
|
||||
PostfixOp::Deref => {
|
||||
let ty = Type::Deref(ctx.b.infer());
|
||||
let dest = ctx.temp(ty);
|
||||
ctx.push(UInstruction::Deref { dst: dest, src: res });
|
||||
dest
|
||||
let dst = ctx.temp(ty);
|
||||
ctx.push(UInstruction::Deref { dst, src: res });
|
||||
dst
|
||||
}
|
||||
PostfixOp::Not => todo!(),
|
||||
}
|
||||
@@ -102,7 +105,7 @@ impl FnLowerable for PExpr {
|
||||
}
|
||||
let dest = ctx.temp(Type::Infer);
|
||||
ctx.push(UInstruction::Call {
|
||||
dst: VarInst { status: , origin: () },
|
||||
dst: dest,
|
||||
f: fe,
|
||||
args: nargs,
|
||||
});
|
||||
@@ -110,26 +113,28 @@ impl FnLowerable for PExpr {
|
||||
}
|
||||
PExpr::Group(e) => e.lower(ctx)?,
|
||||
PExpr::Construct(e, map) => {
|
||||
let dest = ctx.temp(Type::Placeholder);
|
||||
ctx.push(UInstruction::Construct { dst: dest, fields: () });
|
||||
dest
|
||||
let dst = ctx.temp(Type::Infer);
|
||||
let struc = e.lower(ctx)?;
|
||||
let fields = map.lower(ctx)?;
|
||||
ctx.push(UInstruction::Construct { dst, struc, fields });
|
||||
dst
|
||||
}
|
||||
PExpr::If(cond, body) => {
|
||||
let cond = cond.lower(ctx)?;
|
||||
ctx.b.push();
|
||||
ctx.var_stack.push();
|
||||
let mut body_ctx = ctx.branch();
|
||||
body.lower(&mut body_ctx);
|
||||
let body = body_ctx.instructions;
|
||||
ctx.b.pop();
|
||||
ctx.var_stack.pop();
|
||||
ctx.push(UInstruction::If { cond, body });
|
||||
return None;
|
||||
}
|
||||
PExpr::Loop(body) => {
|
||||
ctx.b.push();
|
||||
ctx.var_stack.push();
|
||||
let mut body_ctx = ctx.branch();
|
||||
body.lower(&mut body_ctx);
|
||||
let body = body_ctx.instructions;
|
||||
ctx.b.pop();
|
||||
ctx.var_stack.pop();
|
||||
ctx.push(UInstruction::Loop { body });
|
||||
return None;
|
||||
}
|
||||
|
||||
+61
-27
@@ -1,12 +1,16 @@
|
||||
use std::collections::HashMap;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
use super::{CompilerMsg, CompilerOutput, FileSpan, FnLowerable, Imports, Node, PFunction};
|
||||
use crate::{
|
||||
ir::{
|
||||
FnID, Origin, Typable, Type, UFunc, UInstrInst, UInstruction, UModuleBuilder, UVar, VarID,
|
||||
VarInst, VarStatus,
|
||||
FnID, GenericID, ModPath, Origin, Typable, Type, UFunc, UInstrInst, UInstruction,
|
||||
UModuleBuilder, VarID, VarInst, VarInstID, VarStatus,
|
||||
},
|
||||
parser, util::NameStack,
|
||||
parser,
|
||||
util::NameStack,
|
||||
};
|
||||
|
||||
impl Node<PFunction> {
|
||||
@@ -32,13 +36,9 @@ impl PFunction {
|
||||
) -> Option<FnID> {
|
||||
let header = self.header.as_ref()?;
|
||||
let name = header.name.as_ref()?.0.clone();
|
||||
let (generic_args, args, ret) = if let Some(header) = self.header.as_ref() {
|
||||
let (generics, args, ret) = if let Some(header) = self.header.as_ref() {
|
||||
(
|
||||
header
|
||||
.gargs
|
||||
.iter()
|
||||
.map(|a| Some(a.lower(b, output)))
|
||||
.collect(),
|
||||
header.gargs.iter().flat_map(|a| a.lower(b)).collect(),
|
||||
header
|
||||
.args
|
||||
.iter()
|
||||
@@ -50,27 +50,32 @@ impl PFunction {
|
||||
},
|
||||
)
|
||||
} else {
|
||||
(Vec::new(), Vec::new(), b.error)
|
||||
(Vec::new(), Vec::new(), b.tc.error)
|
||||
};
|
||||
let gargs = generics.iter().map(|g| g.1).collect();
|
||||
let generics = generics.into_iter().collect();
|
||||
let instructions = {
|
||||
let mut var_stack = Vec::new();
|
||||
let mut var_stack = NameStack::new();
|
||||
let mut ctx = FnLowerCtx {
|
||||
instructions: Vec::new(),
|
||||
var_stack: &mut var_stack,
|
||||
b,
|
||||
output,
|
||||
origin: self.body.origin,
|
||||
generics: &generics,
|
||||
imports,
|
||||
};
|
||||
if let Some(src) = self.body.lower(&mut ctx) {
|
||||
ctx.instructions.push(UInstrInst {
|
||||
origin: src.origin,
|
||||
let res = self.body.lower(&mut ctx);
|
||||
let mut instructions = ctx.instructions;
|
||||
if let Some(src) = res {
|
||||
let origin = b.vars_insts[src].origin;
|
||||
instructions.push(UInstrInst {
|
||||
origin,
|
||||
i: UInstruction::Ret { src },
|
||||
});
|
||||
}
|
||||
ctx.instructions
|
||||
instructions
|
||||
};
|
||||
let gargs = args.iter().map(|a| b.vars[a].ty).collect();
|
||||
let f = UFunc {
|
||||
origin,
|
||||
gargs,
|
||||
@@ -90,18 +95,32 @@ pub struct FnLowerCtx<'a, 'b> {
|
||||
pub origin: FileSpan,
|
||||
pub imports: &'a mut Imports,
|
||||
pub var_stack: &'a mut NameStack<VarID>,
|
||||
pub generics: &'a HashMap<String, GenericID>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> FnLowerCtx<'a, 'b> {
|
||||
pub fn var(&mut self, node: &Node<parser::PIdent>) -> VarInst {
|
||||
if let Some(n) = node.as_ref() {
|
||||
if let Some(&var) = self.var_stack.search(&n.0) {
|
||||
return VarInst {
|
||||
status: VarStatus::Res(var),
|
||||
origin: node.origin,
|
||||
pub fn var(&mut self, node: &Node<parser::PIdent>) -> VarInstID {
|
||||
let inst = VarInst {
|
||||
status: if let Some(n) = node.as_ref() {
|
||||
if let Some(&var) = self.var_stack.search(&n.0) {
|
||||
VarStatus::Var(var)
|
||||
} else {
|
||||
VarStatus::Unres {
|
||||
path: ModPath {
|
||||
id: self.b.module,
|
||||
path: Vec::new(),
|
||||
},
|
||||
name: n.0.clone(),
|
||||
gargs: Vec::new(),
|
||||
fields: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
VarStatus::Cooked
|
||||
},
|
||||
origin: node.origin,
|
||||
};
|
||||
self.def_var_inst(inst)
|
||||
}
|
||||
pub fn err(&mut self, msg: String) {
|
||||
self.output.err(CompilerMsg::new(msg, self.origin))
|
||||
@@ -109,7 +128,7 @@ impl<'a, 'b> FnLowerCtx<'a, 'b> {
|
||||
pub fn err_at(&mut self, span: FileSpan, msg: String) {
|
||||
self.output.err(CompilerMsg::new(msg, span))
|
||||
}
|
||||
pub fn temp<T: Typable>(&mut self, ty: Type) -> VarInst {
|
||||
pub fn temp<T: Typable>(&mut self, ty: T) -> VarInstID {
|
||||
self.b.temp_var(self.origin, ty)
|
||||
}
|
||||
pub fn push(&mut self, i: UInstruction) {
|
||||
@@ -118,10 +137,11 @@ impl<'a, 'b> FnLowerCtx<'a, 'b> {
|
||||
pub fn push_at(&mut self, i: UInstruction, span: FileSpan) {
|
||||
self.instructions.push(UInstrInst { i, origin: span });
|
||||
}
|
||||
pub fn branch(&'a mut self) -> FnLowerCtx<'a, 'b> {
|
||||
pub fn branch<'c>(&'c mut self) -> FnLowerCtx<'c, 'b> {
|
||||
FnLowerCtx {
|
||||
b: self.b,
|
||||
instructions: Vec::new(),
|
||||
generics: self.generics,
|
||||
var_stack: self.var_stack,
|
||||
output: self.output,
|
||||
origin: self.origin,
|
||||
@@ -129,3 +149,17 @@ impl<'a, 'b> FnLowerCtx<'a, 'b> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'b> Deref for FnLowerCtx<'_, 'b> {
|
||||
type Target = UModuleBuilder<'b>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.b
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for FnLowerCtx<'_, '_> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.b
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{ir::VarInstID, parser::PMap};
|
||||
|
||||
use super::{FnLowerCtx, FnLowerable};
|
||||
|
||||
impl FnLowerable for PMap {
|
||||
type Output = HashMap<String, VarInstID>;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<Self::Output> {
|
||||
Some(
|
||||
self.0
|
||||
.iter()
|
||||
.flat_map(|n| {
|
||||
let def = n.as_ref()?;
|
||||
let name = def.name.as_ref()?.to_string();
|
||||
let expr = def.val.as_ref()?.lower(ctx)?;
|
||||
Some((name, expr))
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ mod expr;
|
||||
mod func;
|
||||
mod struc;
|
||||
mod ty;
|
||||
mod map;
|
||||
|
||||
use super::*;
|
||||
use crate::ir::{Type, UFunc, UModuleBuilder};
|
||||
|
||||
@@ -1,52 +1,18 @@
|
||||
use crate::{
|
||||
common::{CompilerOutput, FileSpan},
|
||||
ir::{StructField, StructID, UInstruction, UModuleBuilder, UProgram, UStruct, VarInst},
|
||||
parser::{Node, PMap, PStruct, PStructFields},
|
||||
ir::{StructField, StructID, UModuleBuilder, UProgram, UStruct},
|
||||
parser::{Node, PStruct, PStructFields},
|
||||
};
|
||||
|
||||
use super::{FnLowerCtx, FnLowerable};
|
||||
|
||||
impl FnLowerable for PMap {
|
||||
type Output = VarInst;
|
||||
fn lower(&self, ctx: &mut FnLowerCtx) -> Option<VarInst> {
|
||||
let ty = self.name.lower(ctx.b, ctx.output);
|
||||
let fields = match &self.fields {
|
||||
PConstructFields::Named(nodes) => nodes
|
||||
.iter()
|
||||
.flat_map(|n| {
|
||||
let def = n.as_ref()?;
|
||||
let name = def.name.as_ref()?.to_string();
|
||||
let expr = def.val.as_ref()?.lower(ctx)?;
|
||||
Some((name, expr))
|
||||
})
|
||||
.collect(),
|
||||
PConstructFields::Tuple(nodes) => nodes
|
||||
.iter()
|
||||
.enumerate()
|
||||
.flat_map(|(i, n)| {
|
||||
let expr = n.as_ref()?.lower(ctx)?;
|
||||
let name = format!("{i}");
|
||||
Some((name, expr))
|
||||
})
|
||||
.collect(),
|
||||
PConstructFields::None => Default::default(),
|
||||
};
|
||||
let id = ctx.temp(ty);
|
||||
ctx.push(UInstruction::Construct { dst: id, fields });
|
||||
Some(id)
|
||||
}
|
||||
}
|
||||
|
||||
impl PStruct {
|
||||
pub fn lower(
|
||||
&self,
|
||||
id: StructID,
|
||||
p: &mut UModuleBuilder,
|
||||
b: &mut UModuleBuilder,
|
||||
output: &mut CompilerOutput,
|
||||
span: FileSpan,
|
||||
) -> Option<()> {
|
||||
p.push();
|
||||
let generics = self.generics.iter().flat_map(|a| a.lower(p)).collect();
|
||||
let generics = self.generics.iter().flat_map(|a| a.lower(b)).collect();
|
||||
let fields = match &self.fields {
|
||||
PStructFields::Named(nodes) => nodes
|
||||
.iter()
|
||||
@@ -54,7 +20,7 @@ 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(p, output);
|
||||
let ty = tynode.lower(b, output);
|
||||
Some((name, ty))
|
||||
})
|
||||
.collect(),
|
||||
@@ -62,7 +28,7 @@ impl PStruct {
|
||||
.iter()
|
||||
.enumerate()
|
||||
.flat_map(|(i, n)| {
|
||||
let ty = n.as_ref()?.lower(p, output, span);
|
||||
let ty = n.as_ref()?.lower(b, output, span);
|
||||
Some((format!("{i}"), ty))
|
||||
})
|
||||
.collect(),
|
||||
@@ -72,13 +38,12 @@ impl PStruct {
|
||||
.map(|(name, ty)| (name, StructField { ty }))
|
||||
.collect();
|
||||
let name = self.name.as_ref()?.to_string();
|
||||
p.def_data(UStruct {
|
||||
b.def_data(UStruct {
|
||||
name,
|
||||
generics,
|
||||
gargs: generics,
|
||||
fields,
|
||||
origin: span,
|
||||
});
|
||||
p.pop();
|
||||
Some(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ impl PType {
|
||||
name: id.0.clone(),
|
||||
origin,
|
||||
});
|
||||
let ty = Type::Unres(ModPath { m: p.module, path });
|
||||
let ty = Type::Unres(ModPath { id: p.module, path });
|
||||
return p.def_ty(ty);
|
||||
}
|
||||
let ty = match ty {
|
||||
@@ -65,7 +65,7 @@ impl PType {
|
||||
origin,
|
||||
});
|
||||
path.reverse();
|
||||
Type::Unres(ModPath { m: p.module, path })
|
||||
Type::Unres(ModPath { id: p.module, path })
|
||||
}
|
||||
PType::Ref(node) => node.lower(p, output).rf(),
|
||||
PType::Generic(node, nodes) => todo!(),
|
||||
@@ -75,12 +75,15 @@ impl PType {
|
||||
}
|
||||
|
||||
impl Node<PGenericDef> {
|
||||
pub fn lower(&self, p: &mut UProgram) -> Option<GenericID> {
|
||||
pub fn lower(&self, p: &mut UProgram) -> Option<(String, GenericID)> {
|
||||
let s = self.as_ref()?;
|
||||
let name = s.name.as_ref()?.to_string();
|
||||
Some(p.def_generic(UGeneric {
|
||||
name,
|
||||
origin: self.origin,
|
||||
}))
|
||||
Some((
|
||||
name.clone(),
|
||||
p.def_generic(UGeneric {
|
||||
name,
|
||||
origin: self.origin,
|
||||
}),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use super::{
|
||||
util::parse_list, Node, PBlock, PIdent, PType, PVarDef, Parsable, ParseResult, ParserCtx,
|
||||
Symbol,
|
||||
util::parse_list, Node, PBlock, PGenericDef, PIdent, PType, PVarDef, Parsable, ParseResult,
|
||||
ParserCtx, Symbol,
|
||||
};
|
||||
use std::fmt::Debug;
|
||||
|
||||
pub struct PFunctionHeader {
|
||||
pub name: Node<PIdent>,
|
||||
pub args: Vec<Node<PVarDef>>,
|
||||
pub gargs: Vec<Node<PType>>,
|
||||
pub gargs: Vec<Node<PGenericDef>>,
|
||||
pub ret: Option<Node<PType>>,
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ pub struct PStruct {
|
||||
pub fields: PStructFields,
|
||||
}
|
||||
|
||||
pub struct PMap(Vec<Node<PFieldDef>>);
|
||||
pub struct PMap(pub Vec<Node<PFieldDef>>);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum PStructFields {
|
||||
|
||||
Reference in New Issue
Block a user