moving to desktop
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::ir::{AsmBlockArgType, Size, StructTy, SymbolSpace, Type, UFunc, UInstrInst, VarOffset};
|
use crate::ir::{
|
||||||
|
AsmBlockArgType, FnID, Size, GenericTy, SymbolSpace, Type, UFunc, UInstrInst, VarOffset,
|
||||||
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
IRLFunction, LInstruction, Len, Symbol, SymbolSpaceBuilder, UInstruction, UProgram, VarID,
|
IRLFunction, LInstruction, Len, Symbol, SymbolSpaceBuilder, UInstruction, UProgram, VarID,
|
||||||
@@ -14,15 +16,11 @@ pub struct LProgram {
|
|||||||
// NOTE: there are THREE places here where I specify size (8)
|
// NOTE: there are THREE places here where I specify size (8)
|
||||||
|
|
||||||
impl LProgram {
|
impl LProgram {
|
||||||
pub fn create(p: &UProgram) -> Result<Self, String> {
|
pub fn create(p: &UProgram, start: FnID) -> Result<Self, String> {
|
||||||
let start = p
|
|
||||||
.names
|
|
||||||
.id::<UFunc>(&[], "crate")
|
|
||||||
.ok_or("no start method found")?;
|
|
||||||
let mut ssbuilder = SymbolSpaceBuilder::with_entries(&[start]);
|
let mut ssbuilder = SymbolSpaceBuilder::with_entries(&[start]);
|
||||||
let entry = ssbuilder.func(&start);
|
let entry = ssbuilder.func(&start);
|
||||||
while let Some((sym, i)) = ssbuilder.pop_fn() {
|
while let Some((sym, i)) = ssbuilder.pop_fn() {
|
||||||
let f = p.fns[i.0].as_ref().unwrap();
|
let f = &p.fns[i];
|
||||||
let mut fbuilder = LFunctionBuilder::new(p, &mut ssbuilder);
|
let mut fbuilder = LFunctionBuilder::new(p, &mut ssbuilder);
|
||||||
for i in &f.instructions {
|
for i in &f.instructions {
|
||||||
fbuilder.insert_instr(i);
|
fbuilder.insert_instr(i);
|
||||||
@@ -31,7 +29,7 @@ impl LProgram {
|
|||||||
fbuilder.instrs.push(LInstruction::Ret { src: None });
|
fbuilder.instrs.push(LInstruction::Ret { src: None });
|
||||||
}
|
}
|
||||||
let res = fbuilder.finish(f);
|
let res = fbuilder.finish(f);
|
||||||
ssbuilder.write_fn(sym, res, Some(p.names.path(i).to_string()));
|
ssbuilder.write_fn(sym, res, Some(f.name.clone()));
|
||||||
}
|
}
|
||||||
let sym_space = ssbuilder.finish().expect("we failed the mission");
|
let sym_space = ssbuilder.finish().expect("we failed the mission");
|
||||||
Ok(Self { sym_space, entry })
|
Ok(Self { sym_space, entry })
|
||||||
@@ -376,7 +374,7 @@ impl LFunctionBuilderData<'_> {
|
|||||||
pub fn addr_size(&self) -> Size {
|
pub fn addr_size(&self) -> Size {
|
||||||
64
|
64
|
||||||
}
|
}
|
||||||
pub fn struct_inst(&mut self, p: &UProgram, ty: &StructTy) -> &StructInst {
|
pub fn struct_inst(&mut self, p: &UProgram, ty: &GenericTy) -> &StructInst {
|
||||||
// normally I'd let Some(..) here and return, but polonius does not exist :grief:
|
// normally I'd let Some(..) here and return, but polonius does not exist :grief:
|
||||||
if self.struct_insts.get(ty).is_none() {
|
if self.struct_insts.get(ty).is_none() {
|
||||||
let StructInst { id, args } = ty;
|
let StructInst { id, args } = ty;
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
use crate::common::{CompilerMsg, CompilerOutput, FileSpan};
|
|
||||||
|
|
||||||
use super::{UProgram, Type};
|
|
||||||
|
|
||||||
impl CompilerOutput {
|
|
||||||
pub fn check_assign(&mut self, p: &UProgram, src: &Type, dest: &Type, span: FileSpan) {
|
|
||||||
// TODO: spans
|
|
||||||
if src != dest {
|
|
||||||
if !src.is_resolved() || !dest.is_resolved() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self.err(CompilerMsg {
|
|
||||||
msg: format!(
|
|
||||||
"Cannot assign type '{}' to '{}'",
|
|
||||||
p.type_name(src),
|
|
||||||
p.type_name(dest)
|
|
||||||
),
|
|
||||||
spans: vec![span],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +1,33 @@
|
|||||||
use crate::ir::VarID;
|
use crate::ir::VarID;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
use super::{Origin, UInstruction};
|
use super::{MemberID, ModPath, Origin, UInstruction};
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone)]
|
||||||
pub struct VarInst {
|
pub struct VarInst {
|
||||||
pub id: VarID,
|
pub status: VarStatus,
|
||||||
pub origin: Origin,
|
pub origin: Origin,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum VarStatus {
|
||||||
|
Res(VarID),
|
||||||
|
Unres { mid: ModPath, fields: Vec<MemberID> },
|
||||||
|
Partial { v: VarID, fields: Vec<MemberID> },
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct VarParent {
|
||||||
|
id: VarID,
|
||||||
|
path: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct UInstrInst {
|
pub struct UInstrInst {
|
||||||
pub i: UInstruction,
|
pub i: UInstruction,
|
||||||
pub origin: Origin,
|
pub origin: Origin,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for VarInst {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(f, "{:?}", self.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Debug for UInstrInst {
|
impl Debug for UInstrInst {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "{:?}", self.i)
|
write!(f, "{:?}", self.i)
|
||||||
|
|||||||
@@ -73,7 +73,8 @@ impl std::fmt::Debug for UInstruction {
|
|||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Mv { dst: dest, src } => write!(f, "{dest:?} <- {src:?}")?,
|
Self::Mv { dst: dest, src } => write!(f, "{dest:?} <- {src:?}")?,
|
||||||
Self::Ref { dst: dest, src } => write!(f, "{dest:?} <- &{src:?}")?,
|
Self::Ref { dst: dest, src } => write!(f, "{dest:?} <- {src:?}&")?,
|
||||||
|
Self::Deref { dst: dest, src } => write!(f, "{dest:?} <- {src:?}^")?,
|
||||||
Self::LoadData { dst: dest, src } => write!(f, "{dest:?} <- {src:?}")?,
|
Self::LoadData { dst: dest, src } => write!(f, "{dest:?} <- {src:?}")?,
|
||||||
Self::LoadFn { dst: dest, src } => write!(f, "{dest:?} <- {src:?}")?,
|
Self::LoadFn { dst: dest, src } => write!(f, "{dest:?} <- {src:?}")?,
|
||||||
Self::LoadSlice { dst: dest, src } => write!(f, "{dest:?} <- &[{src:?}]")?,
|
Self::LoadSlice { dst: dest, src } => write!(f, "{dest:?} <- &[{src:?}]")?,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use super::{Type, UInstrInst, UInstruction, UProgram};
|
use super::{Type, UInstrInst, UInstruction};
|
||||||
use crate::{
|
use crate::{
|
||||||
common::FileSpan,
|
common::FileSpan,
|
||||||
ir::{Len, ID},
|
ir::{Len, ID},
|
||||||
@@ -12,7 +12,7 @@ pub struct UFunc {
|
|||||||
pub name: String,
|
pub name: String,
|
||||||
pub origin: Origin,
|
pub origin: Origin,
|
||||||
pub args: Vec<VarID>,
|
pub args: Vec<VarID>,
|
||||||
pub argtys: Vec<TypeID>,
|
pub gargs: Vec<TypeID>,
|
||||||
pub ret: TypeID,
|
pub ret: TypeID,
|
||||||
pub instructions: Vec<UInstrInst>,
|
pub instructions: Vec<UInstrInst>,
|
||||||
}
|
}
|
||||||
@@ -41,13 +41,8 @@ pub struct UVar {
|
|||||||
pub name: String,
|
pub name: String,
|
||||||
pub origin: Origin,
|
pub origin: Origin,
|
||||||
pub ty: TypeID,
|
pub ty: TypeID,
|
||||||
pub res: UVarTy,
|
pub parent: Option<VarID>,
|
||||||
}
|
pub children: Vec<VarID>,
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct VarParent {
|
|
||||||
id: VarID,
|
|
||||||
path: Vec<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||||
@@ -62,25 +57,6 @@ pub struct ModPath {
|
|||||||
pub path: Vec<MemberID>,
|
pub path: Vec<MemberID>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub enum UVarTy {
|
|
||||||
Ptr(VarID),
|
|
||||||
/// fully resolved & typed
|
|
||||||
Res {
|
|
||||||
parent: Option<VarParent>,
|
|
||||||
},
|
|
||||||
/// module doesn't exist yet
|
|
||||||
Unres {
|
|
||||||
path: ModPath,
|
|
||||||
fields: Vec<MemberID>,
|
|
||||||
},
|
|
||||||
/// parent var exists but not typed enough for this field path
|
|
||||||
Partial {
|
|
||||||
v: VarID,
|
|
||||||
fields: Vec<MemberID>,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
|
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
|
||||||
pub struct VarOffset {
|
pub struct VarOffset {
|
||||||
pub id: VarID,
|
pub id: VarID,
|
||||||
@@ -117,12 +93,6 @@ pub enum Member {
|
|||||||
pub type Origin = FileSpan;
|
pub type Origin = FileSpan;
|
||||||
|
|
||||||
impl UFunc {
|
impl UFunc {
|
||||||
pub fn ty(&self, program: &UProgram) -> Type {
|
|
||||||
Type::Fn {
|
|
||||||
args: self.argtys.clone(),
|
|
||||||
ret: Box::new(self.ret.clone()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn flat_iter(&self) -> impl Iterator<Item = &UInstrInst> {
|
pub fn flat_iter(&self) -> impl Iterator<Item = &UInstrInst> {
|
||||||
InstrIter::new(self.instructions.iter())
|
InstrIter::new(self.instructions.iter())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
mod assoc;
|
mod assoc;
|
||||||
mod error;
|
|
||||||
mod inst;
|
mod inst;
|
||||||
mod instr;
|
mod instr;
|
||||||
mod kind;
|
mod kind;
|
||||||
@@ -11,7 +10,6 @@ mod resolve;
|
|||||||
use super::*;
|
use super::*;
|
||||||
use assoc::*;
|
use assoc::*;
|
||||||
|
|
||||||
pub use assoc::Idents;
|
|
||||||
pub use inst::*;
|
pub use inst::*;
|
||||||
pub use instr::*;
|
pub use instr::*;
|
||||||
pub use kind::*;
|
pub use kind::*;
|
||||||
|
|||||||
@@ -12,6 +12,11 @@ pub struct UProgram {
|
|||||||
pub generics: Vec<UGeneric>,
|
pub generics: Vec<UGeneric>,
|
||||||
pub vars: Vec<UVar>,
|
pub vars: Vec<UVar>,
|
||||||
pub types: Vec<Type>,
|
pub types: Vec<Type>,
|
||||||
|
|
||||||
|
pub unres_vars: Vec<VarID>,
|
||||||
|
pub unres_tys: Vec<TypeID>,
|
||||||
|
pub unit: TypeID,
|
||||||
|
pub error: TypeID,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UModuleBuilder<'a> {
|
pub struct UModuleBuilder<'a> {
|
||||||
@@ -22,6 +27,9 @@ pub struct UModuleBuilder<'a> {
|
|||||||
|
|
||||||
impl UProgram {
|
impl UProgram {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
|
let mut types = Vec::new();
|
||||||
|
let unit = Self::push_id(&mut types, Type::Unit);
|
||||||
|
let error = Self::push_id(&mut types, Type::Error);
|
||||||
Self {
|
Self {
|
||||||
fns: Vec::new(),
|
fns: Vec::new(),
|
||||||
vars: Vec::new(),
|
vars: Vec::new(),
|
||||||
@@ -30,24 +38,36 @@ impl UProgram {
|
|||||||
generics: Vec::new(),
|
generics: Vec::new(),
|
||||||
data: Vec::new(),
|
data: Vec::new(),
|
||||||
modules: Vec::new(),
|
modules: Vec::new(),
|
||||||
|
unres_vars: Vec::new(),
|
||||||
|
unres_tys: Vec::new(),
|
||||||
|
error,
|
||||||
|
unit,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn instantiate_type(&mut self, ty: Type) {
|
pub fn inst_type(&mut self, ty: TypeID, gs: Vec<TypeID>) -> TypeID {
|
||||||
self.def_ty(match ty {
|
let ty = match &self.types[ty] {
|
||||||
Type::Ref(node) => Type::Ref(node.lower()),
|
Type::Ref(id) => Type::Ref(self.inst_type(*id, gs)),
|
||||||
Type::Generic(node, nodes) => todo!(),
|
Type::Generic(id) => return gs[id.0],
|
||||||
Type::Ident(node) => todo!(),
|
Type::Bits(b) => Type::Bits(*b),
|
||||||
});
|
Type::Struct(struct_ty) => Type::Struct(struct_ty.clone()),
|
||||||
|
Type::Fn() => todo!(),
|
||||||
|
Type::Deref(id) => todo!(),
|
||||||
|
Type::Slice(id) => todo!(),
|
||||||
|
Type::Array(id, _) => todo!(),
|
||||||
|
Type::Unit => todo!(),
|
||||||
|
Type::Unres(mod_path) => todo!(),
|
||||||
|
Type::Infer => todo!(),
|
||||||
|
Type::Error => todo!(),
|
||||||
|
};
|
||||||
|
self.def_ty(ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn infer(&mut self) -> TypeID {
|
pub fn infer(&mut self) -> TypeID {
|
||||||
self.def_ty(Type::Infer)
|
self.def_ty(Type::Infer)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn error(&mut self) -> TypeID {
|
pub fn set_type(id: TypeID, ty: Type) {}
|
||||||
self.def_ty(Type::Error)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn def_var(&mut self, v: UVar) -> VarID {
|
pub fn def_var(&mut self, v: UVar) -> VarID {
|
||||||
Self::push_id(&mut self.vars, v)
|
Self::push_id(&mut self.vars, v)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use super::{Origin, StructTy, Type, TypeID, TypeIDed, UInstruction, UProgram, UStruct, UVar};
|
use super::{Origin, GenericTy, Type, TypeID, TypeIDed, UInstruction, UProgram, UStruct, UVar};
|
||||||
use crate::common::{CompilerMsg, CompilerOutput};
|
use crate::common::{CompilerMsg, CompilerOutput};
|
||||||
use std::{collections::HashMap, ops::BitOrAssign};
|
use std::{collections::HashMap, ops::BitOrAssign};
|
||||||
|
|
||||||
@@ -65,10 +65,6 @@ impl UProgram {
|
|||||||
format!("Type of {:?} cannot be inferred", var.name),
|
format!("Type of {:?} cannot be inferred", var.name),
|
||||||
var.origin,
|
var.origin,
|
||||||
)),
|
)),
|
||||||
Type::Placeholder => output.err(CompilerMsg::new(
|
|
||||||
format!("Var {:?} still placeholder!", var.name),
|
|
||||||
var.origin,
|
|
||||||
)),
|
|
||||||
Type::Unres(_) => output.err(CompilerMsg::new(
|
Type::Unres(_) => output.err(CompilerMsg::new(
|
||||||
format!("Var {:?} type still unresolved!", var.name),
|
format!("Var {:?} type still unresolved!", var.name),
|
||||||
var.origin,
|
var.origin,
|
||||||
@@ -91,11 +87,12 @@ pub fn resolve_instr(data: &mut ResData, i: &UInstruction) -> InstrRes {
|
|||||||
let mut uf = InstrRes::Finished;
|
let mut uf = InstrRes::Finished;
|
||||||
match &i {
|
match &i {
|
||||||
UInstruction::Call { dst, f, args } => {
|
UInstruction::Call { dst, f, args } => {
|
||||||
let fty = data.vars[f.id].ty;
|
let ftyid = data.vars[f.id].ty;
|
||||||
let Type::Fn { args: fargs, ret } = &data.types[fty] else {
|
let fty = &data.types[ftyid];
|
||||||
|
let Type::Fn { args: fargs, ret } = fty else {
|
||||||
data.errs.push(ResErr::NotCallable {
|
data.errs.push(ResErr::NotCallable {
|
||||||
origin: f.origin,
|
origin: f.origin,
|
||||||
ty: fty,
|
ty: ftyid,
|
||||||
});
|
});
|
||||||
return InstrRes::Finished;
|
return InstrRes::Finished;
|
||||||
};
|
};
|
||||||
@@ -131,7 +128,7 @@ pub fn resolve_instr(data: &mut ResData, i: &UInstruction) -> InstrRes {
|
|||||||
let dest_ty = get(vars, dst.id)?;
|
let dest_ty = get(vars, dst.id)?;
|
||||||
let Type::Struct(sty) = dest_ty else {};
|
let Type::Struct(sty) = dest_ty else {};
|
||||||
let id = sty.id;
|
let id = sty.id;
|
||||||
let Some(struc) = self.get(id) else {};
|
let Some(struc) = get(id) else {};
|
||||||
let mut new = HashMap::new();
|
let mut new = HashMap::new();
|
||||||
for (name, field) in &struc.fields {
|
for (name, field) in &struc.fields {
|
||||||
let Some(src) = fields.get(name) else {
|
let Some(src) = fields.get(name) else {
|
||||||
@@ -155,7 +152,7 @@ pub fn resolve_instr(data: &mut ResData, i: &UInstruction) -> InstrRes {
|
|||||||
args[i] = ty;
|
args[i] = ty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set(vars, dst.id, Type::Struct(StructTy { id, args }));
|
set(vars, dst.id, Type::Struct(GenericTy { id, args }));
|
||||||
}
|
}
|
||||||
UInstruction::If { cond, body } => {
|
UInstruction::If { cond, body } => {
|
||||||
for i in body {
|
for i in body {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use super::{FnID, GenericID, Len, ModPath, StructID, TypeID, UVar, VarID, VarInst};
|
use super::{GenericID, Len, ModPath, TypeID, UFunc, UProgram, UStruct, UVar, VarID, VarInst};
|
||||||
|
use crate::ir::ID;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
||||||
pub struct FieldRef {
|
pub struct FieldRef {
|
||||||
@@ -7,16 +8,16 @@ pub struct FieldRef {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||||
pub struct StructTy {
|
pub struct GenericTy<T> {
|
||||||
pub id: StructID,
|
pub id: ID<T>,
|
||||||
pub args: Vec<TypeID>,
|
pub args: Vec<TypeID>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
Bits(u32),
|
Bits(u32),
|
||||||
Struct(StructTy),
|
Struct(GenericTy<UStruct>),
|
||||||
Fn(FnID),
|
Fn(GenericTy<UFunc>),
|
||||||
Ref(TypeID),
|
Ref(TypeID),
|
||||||
Deref(TypeID),
|
Deref(TypeID),
|
||||||
Slice(TypeID),
|
Slice(TypeID),
|
||||||
@@ -27,7 +28,21 @@ pub enum Type {
|
|||||||
Generic(GenericID),
|
Generic(GenericID),
|
||||||
Infer,
|
Infer,
|
||||||
Error,
|
Error,
|
||||||
Placeholder,
|
}
|
||||||
|
|
||||||
|
impl Type {
|
||||||
|
pub fn rf(self, p: &mut UProgram) -> Self {
|
||||||
|
p.def_ty(self).rf()
|
||||||
|
}
|
||||||
|
pub fn derf(self, p: &mut UProgram) -> Self {
|
||||||
|
p.def_ty(self).derf()
|
||||||
|
}
|
||||||
|
pub fn arr(self, p: &mut UProgram, len: Len) -> Self {
|
||||||
|
p.def_ty(self).arr(len)
|
||||||
|
}
|
||||||
|
pub fn slice(self, p: &mut UProgram) -> Self {
|
||||||
|
p.def_ty(self).slice()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeID {
|
impl TypeID {
|
||||||
@@ -46,9 +61,6 @@ impl TypeID {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Type {
|
impl Type {
|
||||||
pub fn is_resolved(&self) -> bool {
|
|
||||||
!matches!(self, Self::Error | Self::Placeholder | Self::Infer)
|
|
||||||
}
|
|
||||||
pub fn bx(self) -> Box<Self> {
|
pub fn bx(self) -> Box<Self> {
|
||||||
Box::new(self)
|
Box::new(self)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ pub fn arg_to_var(node: &Node<PAsmArg>, ctx: &mut FnLowerCtx) -> Option<VarInst>
|
|||||||
);
|
);
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
ctx.get_var(node)
|
ctx.var(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RegRef {
|
impl RegRef {
|
||||||
@@ -184,7 +184,7 @@ impl RegRef {
|
|||||||
let reg = Reg::from_ident(node, ctx)?;
|
let reg = Reg::from_ident(node, ctx)?;
|
||||||
Self::Reg(reg)
|
Self::Reg(reg)
|
||||||
}
|
}
|
||||||
PAsmArg::Ref(node) => Self::Var(ctx.get_var(node)?),
|
PAsmArg::Ref(node) => Self::Var(ctx.var(node)?),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use crate::ir::{UProgram, UVar, VarInst};
|
use crate::ir::{UProgram, UVar, VarID, VarInst};
|
||||||
|
|
||||||
use super::{CompilerOutput, Node, PVarDef};
|
use super::{CompilerOutput, Node, PVarDef};
|
||||||
|
|
||||||
impl Node<PVarDef> {
|
impl Node<PVarDef> {
|
||||||
pub fn lower(&self, program: &mut UProgram, output: &mut CompilerOutput) -> Option<VarInst> {
|
pub fn lower(&self, program: &mut UProgram, output: &mut CompilerOutput) -> Option<VarID> {
|
||||||
let s = self.as_ref()?;
|
let s = self.as_ref()?;
|
||||||
let name = s.name.as_ref().map_or("{error}", |v| v);
|
let name = s.name.as_ref().map_or("{error}", |v| v);
|
||||||
let ty = match &s.ty {
|
let ty = match &s.ty {
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ impl FnLowerable for PExpr {
|
|||||||
Some(match e {
|
Some(match e {
|
||||||
PExpr::Lit(l) => match l {
|
PExpr::Lit(l) => match l {
|
||||||
super::PLiteral::String(s) => {
|
super::PLiteral::String(s) => {
|
||||||
let dest = ctx.b.temp_var(ctx.origin, Type::Bits(8).slice());
|
let dest = ctx.b.temp_var(ctx.origin, Type::Bits(8).slice(ctx.b.p));
|
||||||
let data = s.as_bytes().to_vec();
|
let data = s.as_bytes().to_vec();
|
||||||
let src = ctx.b.def_data(UData {
|
let src = ctx.b.def_data(UData {
|
||||||
name: format!("string \"{}\"", s.replace("\n", "\\n")),
|
name: format!("string \"{}\"", s.replace("\n", "\\n")),
|
||||||
ty: Type::Bits(8).arr(data.len() as u32),
|
ty: Type::Bits(8).arr(ctx.b.p, data.len() as u32),
|
||||||
content: data,
|
content: data,
|
||||||
});
|
});
|
||||||
ctx.push(UInstruction::LoadSlice { dst: dest, src });
|
ctx.push(UInstruction::LoadSlice { dst: dest, src });
|
||||||
@@ -55,7 +55,7 @@ impl FnLowerable for PExpr {
|
|||||||
}
|
}
|
||||||
super::PLiteral::Unit => ctx.b.temp_var(ctx.origin, Type::Unit),
|
super::PLiteral::Unit => ctx.b.temp_var(ctx.origin, Type::Unit),
|
||||||
},
|
},
|
||||||
PExpr::Ident(i) => ctx.get_var(i),
|
PExpr::Ident(i) => ctx.var(i),
|
||||||
PExpr::BinaryOp(op, e1, e2) => match op {
|
PExpr::BinaryOp(op, e1, e2) => match op {
|
||||||
InfixOp::Add => todo!(),
|
InfixOp::Add => todo!(),
|
||||||
InfixOp::Sub => todo!(),
|
InfixOp::Sub => todo!(),
|
||||||
@@ -77,13 +77,13 @@ impl FnLowerable for PExpr {
|
|||||||
let res = e.lower(ctx)?;
|
let res = e.lower(ctx)?;
|
||||||
match op {
|
match op {
|
||||||
PostfixOp::Ref => {
|
PostfixOp::Ref => {
|
||||||
let ty = ctx.b.vars[res.id].ty.rf();
|
let ty = Type::Ref(ctx.b.infer());
|
||||||
let dest = ctx.temp(ty);
|
let dest = ctx.temp(ty);
|
||||||
ctx.push(UInstruction::Ref { dst: dest, src: res });
|
ctx.push(UInstruction::Ref { dst: dest, src: res });
|
||||||
dest
|
dest
|
||||||
}
|
}
|
||||||
PostfixOp::Deref => {
|
PostfixOp::Deref => {
|
||||||
let ty = ctx.b.vars[res.id].ty.derf();
|
let ty = Type::Deref(ctx.b.infer());
|
||||||
let dest = ctx.temp(ty);
|
let dest = ctx.temp(ty);
|
||||||
ctx.push(UInstruction::Deref { dst: dest, src: res });
|
ctx.push(UInstruction::Deref { dst: dest, src: res });
|
||||||
dest
|
dest
|
||||||
@@ -100,9 +100,9 @@ impl FnLowerable for PExpr {
|
|||||||
let arg = arg.lower(ctx)?;
|
let arg = arg.lower(ctx)?;
|
||||||
nargs.push(arg);
|
nargs.push(arg);
|
||||||
}
|
}
|
||||||
let dest = ctx.temp(Type::Placeholder);
|
let dest = ctx.temp(Type::Infer);
|
||||||
ctx.push(UInstruction::Call {
|
ctx.push(UInstruction::Call {
|
||||||
dst: dest,
|
dst: VarInst { status: , origin: () },
|
||||||
f: fe,
|
f: fe,
|
||||||
args: nargs,
|
args: nargs,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,120 +3,111 @@ use std::collections::HashMap;
|
|||||||
use super::{CompilerMsg, CompilerOutput, FileSpan, FnLowerable, Imports, Node, PFunction};
|
use super::{CompilerMsg, CompilerOutput, FileSpan, FnLowerable, Imports, Node, PFunction};
|
||||||
use crate::{
|
use crate::{
|
||||||
ir::{
|
ir::{
|
||||||
FnID, Idents, Typable, Type, UFunc, UInstrInst, UInstruction, UModuleBuilder, UProgram,
|
FnID, Origin, Typable, Type, UFunc, UInstrInst, UInstruction, UModuleBuilder, UVar, VarID,
|
||||||
UVar, VarID, VarInst,
|
VarInst, VarStatus,
|
||||||
},
|
},
|
||||||
parser,
|
parser, util::NameStack,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl Node<PFunction> {
|
impl Node<PFunction> {
|
||||||
pub fn lower_name(&self, p: &mut UProgram) -> Option<FnID> {
|
|
||||||
self.as_ref()?.lower_name(p)
|
|
||||||
}
|
|
||||||
pub fn lower(
|
pub fn lower(
|
||||||
&self,
|
&self,
|
||||||
id: FnID,
|
b: &mut UModuleBuilder,
|
||||||
p: &mut UProgram,
|
|
||||||
imports: &mut Imports,
|
imports: &mut Imports,
|
||||||
output: &mut CompilerOutput,
|
output: &mut CompilerOutput,
|
||||||
) {
|
) -> Option<FnID> {
|
||||||
if let Some(s) = self.as_ref() {
|
self.as_ref()
|
||||||
s.lower(id, p, imports, output)
|
.map(|s| s.lower(b, imports, output, self.origin))
|
||||||
}
|
.flatten()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PFunction {
|
impl PFunction {
|
||||||
pub fn lower_name(&self, p: &mut UProgram) -> Option<FnID> {
|
|
||||||
let header = self.header.as_ref()?;
|
|
||||||
let name = header.name.as_ref()?;
|
|
||||||
let id = p.def_searchable(name, None, self.header.origin);
|
|
||||||
Some(id)
|
|
||||||
}
|
|
||||||
pub fn lower(
|
pub fn lower(
|
||||||
&self,
|
&self,
|
||||||
id: FnID,
|
b: &mut UModuleBuilder,
|
||||||
p: &mut UProgram,
|
|
||||||
imports: &mut Imports,
|
imports: &mut Imports,
|
||||||
output: &mut CompilerOutput,
|
output: &mut CompilerOutput,
|
||||||
) {
|
origin: Origin,
|
||||||
let name = p.names.name(id).to_string();
|
) -> Option<FnID> {
|
||||||
p.push_name(&name);
|
let header = self.header.as_ref()?;
|
||||||
let (args, ret) = if let Some(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() {
|
||||||
(
|
(
|
||||||
|
header
|
||||||
|
.gargs
|
||||||
|
.iter()
|
||||||
|
.map(|a| Some(a.lower(b, output)))
|
||||||
|
.collect(),
|
||||||
header
|
header
|
||||||
.args
|
.args
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|a| Some(a.lower(p, output)?.id))
|
.flat_map(|a| Some(a.lower(b, output)?))
|
||||||
.collect(),
|
.collect(),
|
||||||
match &header.ret {
|
match &header.ret {
|
||||||
Some(ty) => ty.lower(p, output),
|
Some(ty) => ty.lower(b, output),
|
||||||
None => Type::Unit,
|
None => b.def_ty(Type::Unit),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(Vec::new(), Type::Error)
|
(Vec::new(), Vec::new(), b.error)
|
||||||
};
|
};
|
||||||
let mut ctx = FnLowerCtx {
|
let instructions = {
|
||||||
instructions: Vec::new(),
|
let mut var_stack = Vec::new();
|
||||||
b: p,
|
let mut ctx = FnLowerCtx {
|
||||||
output,
|
instructions: Vec::new(),
|
||||||
origin: self.body.origin,
|
var_stack: &mut var_stack,
|
||||||
imports,
|
b,
|
||||||
|
output,
|
||||||
|
origin: self.body.origin,
|
||||||
|
imports,
|
||||||
|
};
|
||||||
|
if let Some(src) = self.body.lower(&mut ctx) {
|
||||||
|
ctx.instructions.push(UInstrInst {
|
||||||
|
origin: src.origin,
|
||||||
|
i: UInstruction::Ret { src },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
ctx.instructions
|
||||||
};
|
};
|
||||||
if let Some(src) = self.body.lower(&mut ctx) {
|
let gargs = args.iter().map(|a| b.vars[a].ty).collect();
|
||||||
ctx.instructions.push(UInstrInst {
|
|
||||||
i: UInstruction::Ret { src },
|
|
||||||
origin: src.origin,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
let instructions = ctx.instructions;
|
|
||||||
let f = UFunc {
|
let f = UFunc {
|
||||||
|
origin,
|
||||||
|
gargs,
|
||||||
|
name,
|
||||||
args,
|
args,
|
||||||
ret,
|
ret,
|
||||||
instructions,
|
instructions,
|
||||||
};
|
};
|
||||||
p.pop_name();
|
Some(b.def_fn(f))
|
||||||
p.write(id, f)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FnLowerCtx<'a> {
|
pub struct FnLowerCtx<'a, 'b> {
|
||||||
pub b: &'a mut UModuleBuilder<'a>,
|
pub b: &'a mut UModuleBuilder<'b>,
|
||||||
pub instructions: Vec<UInstrInst>,
|
pub instructions: Vec<UInstrInst>,
|
||||||
pub output: &'a mut CompilerOutput,
|
pub output: &'a mut CompilerOutput,
|
||||||
pub origin: FileSpan,
|
pub origin: FileSpan,
|
||||||
pub imports: &'a mut Imports,
|
pub imports: &'a mut Imports,
|
||||||
pub var_stack: Vec<HashMap<String, VarID>>,
|
pub var_stack: &'a mut NameStack<VarID>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FnLowerCtx<'_> {
|
impl<'a, 'b> FnLowerCtx<'a, 'b> {
|
||||||
pub fn get_idents(&mut self, node: &Node<parser::PIdent>) -> Option<Idents> {
|
pub fn var(&mut self, node: &Node<parser::PIdent>) -> VarInst {
|
||||||
let name = node.inner.as_ref()?;
|
if let Some(n) = node.as_ref() {
|
||||||
let res = self.b.get_idents(name);
|
if let Some(&var) = self.var_stack.search(&n.0) {
|
||||||
if res.is_none() {
|
return VarInst {
|
||||||
self.err_at(node.origin, format!("Identifier '{}' not found", name));
|
status: VarStatus::Res(var),
|
||||||
|
origin: node.origin,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
res
|
|
||||||
}
|
|
||||||
pub fn get_var(&mut self, node: &Node<parser::PIdent>) -> VarInst {
|
|
||||||
let ids = self.get_idents(node)?;
|
|
||||||
if ids.get::<UVar>().is_none() {
|
|
||||||
self.err_at(
|
|
||||||
node.origin,
|
|
||||||
format!("Variable '{}' not found", node.inner.as_ref()?),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
ids.get::<UVar>().map(|id| VarInst {
|
|
||||||
id,
|
|
||||||
origin: node.origin,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
pub fn err(&mut self, msg: String) {
|
pub fn err(&mut self, msg: String) {
|
||||||
self.output.err(CompilerMsg::new(self.origin, msg))
|
self.output.err(CompilerMsg::new(msg, self.origin))
|
||||||
}
|
}
|
||||||
pub fn err_at(&mut self, span: FileSpan, msg: String) {
|
pub fn err_at(&mut self, span: FileSpan, msg: String) {
|
||||||
self.output.err(CompilerMsg::new(span, msg))
|
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: Type) -> VarInst {
|
||||||
self.b.temp_var(self.origin, ty)
|
self.b.temp_var(self.origin, ty)
|
||||||
@@ -125,27 +116,13 @@ impl FnLowerCtx<'_> {
|
|||||||
self.push_at(i, self.origin);
|
self.push_at(i, self.origin);
|
||||||
}
|
}
|
||||||
pub fn push_at(&mut self, i: UInstruction, span: FileSpan) {
|
pub fn push_at(&mut self, i: UInstruction, span: FileSpan) {
|
||||||
match i {
|
|
||||||
UInstruction::Mv { dst: dest, src } => todo!(),
|
|
||||||
UInstruction::Ref { dst: dest, src } => todo!(),
|
|
||||||
UInstruction::LoadData { dst: dest, src } => todo!(),
|
|
||||||
UInstruction::LoadSlice { dst: dest, src } => todo!(),
|
|
||||||
UInstruction::LoadFn { dst: dest, src } => todo!(),
|
|
||||||
UInstruction::Call { dst: dest, f, args } => todo!(),
|
|
||||||
UInstruction::AsmBlock { instructions, args } => todo!(),
|
|
||||||
UInstruction::Ret { src } => todo!(),
|
|
||||||
UInstruction::Construct { dst: dest, fields } => todo!(),
|
|
||||||
UInstruction::If { cond, body } => todo!(),
|
|
||||||
UInstruction::Loop { body } => todo!(),
|
|
||||||
UInstruction::Break => todo!(),
|
|
||||||
UInstruction::Continue => todo!(),
|
|
||||||
}
|
|
||||||
self.instructions.push(UInstrInst { i, origin: span });
|
self.instructions.push(UInstrInst { i, origin: span });
|
||||||
}
|
}
|
||||||
pub fn branch<'a>(&'a mut self) -> FnLowerCtx<'a> {
|
pub fn branch(&'a mut self) -> FnLowerCtx<'a, 'b> {
|
||||||
FnLowerCtx {
|
FnLowerCtx {
|
||||||
b: self.b,
|
b: self.b,
|
||||||
instructions: Vec::new(),
|
instructions: Vec::new(),
|
||||||
|
var_stack: self.var_stack,
|
||||||
output: self.output,
|
output: self.output,
|
||||||
origin: self.origin,
|
origin: self.origin,
|
||||||
imports: self.imports,
|
imports: self.imports,
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ mod struc;
|
|||||||
mod ty;
|
mod ty;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::ir::{Type, UFunc, UProgram};
|
use crate::ir::{Type, UFunc, UModuleBuilder};
|
||||||
|
|
||||||
impl PModule {
|
impl PModule {
|
||||||
pub fn lower(
|
pub fn lower(
|
||||||
&self,
|
&self,
|
||||||
path: Vec<String>,
|
path: Vec<String>,
|
||||||
p: &mut UProgram,
|
p: &mut UModuleBuilder,
|
||||||
imports: &mut Imports,
|
imports: &mut Imports,
|
||||||
output: &mut CompilerOutput,
|
output: &mut CompilerOutput,
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -9,14 +9,14 @@ impl Node<Box<PType>> {
|
|||||||
pub fn lower(&self, p: &mut UModuleBuilder, output: &mut CompilerOutput) -> TypeID {
|
pub fn lower(&self, p: &mut UModuleBuilder, output: &mut CompilerOutput) -> TypeID {
|
||||||
self.as_ref()
|
self.as_ref()
|
||||||
.map(|t| t.lower(p, output, self.origin))
|
.map(|t| t.lower(p, output, self.origin))
|
||||||
.unwrap_or(p.error())
|
.unwrap_or(p.error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Node<PType> {
|
impl Node<PType> {
|
||||||
pub fn lower(&self, p: &mut UModuleBuilder, output: &mut CompilerOutput) -> TypeID {
|
pub fn lower(&self, p: &mut UModuleBuilder, output: &mut CompilerOutput) -> TypeID {
|
||||||
self.as_ref()
|
self.as_ref()
|
||||||
.map(|t| t.lower(p, output, self.origin))
|
.map(|t| t.lower(p, output, self.origin))
|
||||||
.unwrap_or(p.error())
|
.unwrap_or(p.error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ impl PType {
|
|||||||
while let PType::Member(node, ident) = ty {
|
while let PType::Member(node, ident) = ty {
|
||||||
ty = if let Some(t) = node.as_ref() {
|
ty = if let Some(t) = node.as_ref() {
|
||||||
let Some(name) = ident.as_ref() else {
|
let Some(name) = ident.as_ref() else {
|
||||||
return p.error();
|
return p.error;
|
||||||
};
|
};
|
||||||
origin = node.origin;
|
origin = node.origin;
|
||||||
path.push(MemberID {
|
path.push(MemberID {
|
||||||
@@ -43,18 +43,19 @@ impl PType {
|
|||||||
});
|
});
|
||||||
&**t
|
&**t
|
||||||
} else {
|
} else {
|
||||||
return p.error();
|
return p.error;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if !path.is_empty() {
|
if !path.is_empty() {
|
||||||
let PType::Ident(id) = ty else {
|
let PType::Ident(id) = ty else {
|
||||||
return p.error();
|
return p.error;
|
||||||
};
|
};
|
||||||
path.push(MemberID {
|
path.push(MemberID {
|
||||||
name: id.0.clone(),
|
name: id.0.clone(),
|
||||||
origin,
|
origin,
|
||||||
});
|
});
|
||||||
return p.def_ty(Type::Unres(ModPath { m: p.module, path }));
|
let ty = Type::Unres(ModPath { m: p.module, path });
|
||||||
|
return p.def_ty(ty);
|
||||||
}
|
}
|
||||||
let ty = match ty {
|
let ty = match ty {
|
||||||
PType::Member(_, _) => unreachable!(),
|
PType::Member(_, _) => unreachable!(),
|
||||||
@@ -70,31 +71,6 @@ impl PType {
|
|||||||
PType::Generic(node, nodes) => todo!(),
|
PType::Generic(node, nodes) => todo!(),
|
||||||
};
|
};
|
||||||
p.def_ty(ty)
|
p.def_ty(ty)
|
||||||
// let Some(name) = self.name.as_ref() else {
|
|
||||||
// return p.error();
|
|
||||||
// };
|
|
||||||
// let ids = p.get_idents(name);
|
|
||||||
// // TODO: should generics always take precedence?
|
|
||||||
// if let Some(id) = ids.and_then(|ids| ids.get::<Type>()) {
|
|
||||||
// Type::Generic { id }
|
|
||||||
// } else if let Some(id) = ids.and_then(|ids| ids.get::<UStruct>()) {
|
|
||||||
// let args = self.args.iter().map(|n| n.lower(p, output)).collect();
|
|
||||||
// Type::Struct(StructInst { id, args })
|
|
||||||
// } else if let Ok(num) = name.parse::<u32>() {
|
|
||||||
// Type::Bits(num)
|
|
||||||
// } else {
|
|
||||||
// match name.as_str() {
|
|
||||||
// "slice" => {
|
|
||||||
// let inner = self.args[0].lower(p, output);
|
|
||||||
// Type::Slice(Box::new(inner))
|
|
||||||
// }
|
|
||||||
// "_" => Type::Infer,
|
|
||||||
// _ => {
|
|
||||||
// output.err(CompilerMsg::from_span(span, "Type not found".to_string()));
|
|
||||||
// Type::Error
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
use super::{
|
use super::{
|
||||||
util::parse_list, PBlock, PIdent, Node, Parsable, ParseResult, ParserCtx,
|
util::parse_list, Node, PBlock, PIdent, PType, PVarDef, Parsable, ParseResult, ParserCtx,
|
||||||
Symbol, PType, PVarDef,
|
Symbol,
|
||||||
};
|
};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
pub struct PFunctionHeader {
|
pub struct PFunctionHeader {
|
||||||
pub name: Node<PIdent>,
|
pub name: Node<PIdent>,
|
||||||
pub args: Vec<Node<PVarDef>>,
|
pub args: Vec<Node<PVarDef>>,
|
||||||
|
pub gargs: Vec<Node<PType>>,
|
||||||
pub ret: Option<Node<PType>>,
|
pub ret: Option<Node<PType>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,6 +19,12 @@ pub struct PFunction {
|
|||||||
impl Parsable for PFunctionHeader {
|
impl Parsable for PFunctionHeader {
|
||||||
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
|
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
|
||||||
let name = ctx.parse()?;
|
let name = ctx.parse()?;
|
||||||
|
let generic_args = if ctx.expect_peek()?.is_symbol(Symbol::OpenAngle) {
|
||||||
|
ctx.next();
|
||||||
|
parse_list(ctx, Symbol::CloseAngle)?
|
||||||
|
} else {
|
||||||
|
Vec::new()
|
||||||
|
};
|
||||||
ctx.expect_sym(Symbol::OpenParen)?;
|
ctx.expect_sym(Symbol::OpenParen)?;
|
||||||
// let sel = ctx.maybe_parse();
|
// let sel = ctx.maybe_parse();
|
||||||
// if sel.is_some() {
|
// if sel.is_some() {
|
||||||
@@ -39,6 +46,7 @@ impl Parsable for PFunctionHeader {
|
|||||||
ParseResult::Ok(Self {
|
ParseResult::Ok(Self {
|
||||||
name,
|
name,
|
||||||
args,
|
args,
|
||||||
|
gargs: generic_args,
|
||||||
ret,
|
ret,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ impl Parsable for PType {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ParseResult::Wrap(cur)
|
ParseResult::Node(cur)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
mod padder;
|
mod padder;
|
||||||
mod bits;
|
mod bits;
|
||||||
mod label;
|
mod label;
|
||||||
|
mod name_stack;
|
||||||
|
|
||||||
pub use padder::*;
|
pub use padder::*;
|
||||||
pub use bits::*;
|
pub use bits::*;
|
||||||
pub use label::*;
|
pub use label::*;
|
||||||
|
pub use name_stack::*;
|
||||||
|
|||||||
17
src/util/name_stack.rs
Normal file
17
src/util/name_stack.rs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
pub struct NameStack<T>(Vec<HashMap<String, T>>);
|
||||||
|
|
||||||
|
impl<T> NameStack<T> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self(Vec::new())
|
||||||
|
}
|
||||||
|
pub fn search(&self, name: &str) -> Option<&T> {
|
||||||
|
for level in self.0.iter().rev() {
|
||||||
|
if let Some(v) = level.get(name) {
|
||||||
|
return Some(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user