had a conversation w the code
This commit is contained in:
@@ -75,20 +75,23 @@ fn structer(test: Test) {
|
|||||||
println("");
|
println("");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GTest<T, U> {
|
struct GTest<T, U, V> {
|
||||||
a: T,
|
a: T,
|
||||||
b: U,
|
b: U,
|
||||||
|
c: V,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generic() {
|
fn generic() {
|
||||||
let gt = GTest {
|
let gt = GTest {
|
||||||
a: 39,
|
a: 39,
|
||||||
b: "hello",
|
b: "hello",
|
||||||
|
c: 40,
|
||||||
};
|
};
|
||||||
print("generic: ");
|
print("generic: ");
|
||||||
print_dec(gt.a);
|
print_dec(gt.a);
|
||||||
print(", ");
|
print(", ");
|
||||||
print(gt.b);
|
print(gt.b);
|
||||||
|
print_dec(gt.c);
|
||||||
println("");
|
println("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ impl LProgram {
|
|||||||
pub fn create(p: &UProgram) -> Result<Self, String> {
|
pub fn create(p: &UProgram) -> Result<Self, String> {
|
||||||
let start = p
|
let start = p
|
||||||
.names
|
.names
|
||||||
.lookup::<UFunc>("start")
|
.id::<UFunc>("start")
|
||||||
.ok_or("no start method found")?;
|
.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);
|
||||||
@@ -31,7 +31,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.get(i).to_string()));
|
ssbuilder.write_fn(sym, res, Some(p.names.name(i).to_string()));
|
||||||
}
|
}
|
||||||
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 })
|
||||||
@@ -101,7 +101,7 @@ impl<'a> LFunctionBuilder<'a> {
|
|||||||
};
|
};
|
||||||
self.map_subvar(i);
|
self.map_subvar(i);
|
||||||
let var = self.data.var_offset(self.program, i).expect("var offset");
|
let var = self.data.var_offset(self.program, i).expect("var offset");
|
||||||
if let None = self.stack.get(&var.id) {
|
if !self.stack.contains_key(&var.id) {
|
||||||
let size = self
|
let size = self
|
||||||
.data
|
.data
|
||||||
.size_of_var(self.program, var.id)
|
.size_of_var(self.program, var.id)
|
||||||
@@ -142,7 +142,7 @@ impl<'a> LFunctionBuilder<'a> {
|
|||||||
let sym = self.data.builder.ro_data(
|
let sym = self.data.builder.ro_data(
|
||||||
src,
|
src,
|
||||||
&data.content,
|
&data.content,
|
||||||
Some(self.program.names.get(dest.id).to_string()),
|
Some(self.program.names.name(dest.id).to_string()),
|
||||||
);
|
);
|
||||||
self.instrs.push(LInstruction::LoadData {
|
self.instrs.push(LInstruction::LoadData {
|
||||||
dest: dest.id,
|
dest: dest.id,
|
||||||
@@ -163,7 +163,7 @@ impl<'a> LFunctionBuilder<'a> {
|
|||||||
let sym = self.data.builder.ro_data(
|
let sym = self.data.builder.ro_data(
|
||||||
src,
|
src,
|
||||||
&data.content,
|
&data.content,
|
||||||
Some(self.program.names.get(dest.id).to_string()),
|
Some(self.program.names.name(dest.id).to_string()),
|
||||||
);
|
);
|
||||||
self.instrs.push(LInstruction::LoadAddr {
|
self.instrs.push(LInstruction::LoadAddr {
|
||||||
dest: dest.id,
|
dest: dest.id,
|
||||||
@@ -193,7 +193,7 @@ impl<'a> LFunctionBuilder<'a> {
|
|||||||
UInstruction::Call { dest, f, args } => {
|
UInstruction::Call { dest, f, args } => {
|
||||||
self.alloc_stack(dest.id);
|
self.alloc_stack(dest.id);
|
||||||
self.makes_call = true;
|
self.makes_call = true;
|
||||||
let fid = &self.program.fn_map[&f.id];
|
let fid = &self.program.fn_var.fun(f.id).expect("a");
|
||||||
let sym = self.builder.func(fid);
|
let sym = self.builder.func(fid);
|
||||||
let ret_size = self
|
let ret_size = self
|
||||||
.data
|
.data
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
|
use super::{Type, UInstrInst, UInstruction, UProgram};
|
||||||
use crate::{
|
use crate::{
|
||||||
common::FileSpan,
|
common::FileSpan,
|
||||||
ir::{Len, Named, ID},
|
ir::{Len, Named, ID},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Type, UInstrInst, UInstruction, UProgram};
|
|
||||||
use std::{collections::HashMap, fmt::Debug};
|
use std::{collections::HashMap, fmt::Debug};
|
||||||
|
|
||||||
pub struct UFunc {
|
pub struct UFunc {
|
||||||
pub args: Vec<VarID>,
|
pub args: Vec<VarID>,
|
||||||
pub ret: Type,
|
pub ret: Type,
|
||||||
pub origin: Origin,
|
|
||||||
pub instructions: Vec<UInstrInst>,
|
pub instructions: Vec<UInstrInst>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,7 +20,6 @@ pub struct StructField {
|
|||||||
pub struct UStruct {
|
pub struct UStruct {
|
||||||
pub fields: HashMap<String, StructField>,
|
pub fields: HashMap<String, StructField>,
|
||||||
pub generics: Vec<GenericID>,
|
pub generics: Vec<GenericID>,
|
||||||
pub origin: Origin,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -32,7 +29,6 @@ pub struct UGeneric {}
|
|||||||
pub struct UVar {
|
pub struct UVar {
|
||||||
pub parent: Option<FieldRef>,
|
pub parent: Option<FieldRef>,
|
||||||
pub ty: Type,
|
pub ty: Type,
|
||||||
pub origin: Origin,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
|
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
|
||||||
@@ -50,7 +46,6 @@ pub struct FieldRef {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct UData {
|
pub struct UData {
|
||||||
pub ty: Type,
|
pub ty: Type,
|
||||||
pub origin: Origin,
|
|
||||||
pub content: Vec<u8>,
|
pub content: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +96,14 @@ impl<'a> Iterator for InstrIter<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_kind {
|
macro_rules! impl_kind {
|
||||||
|
// TRUST THIS IS SANE!!! KEEP THE CODE DRY AND SAFE!!!!!!
|
||||||
($struc:ty, $idx:expr, $field:ident, $name:expr) => {
|
($struc:ty, $idx:expr, $field:ident, $name:expr) => {
|
||||||
|
impl_kind!($struc, $idx, $field, $name, nofin);
|
||||||
|
impl Finish for $struc {
|
||||||
|
fn finish(_: &mut UProgram, _: ID<Self>) {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
($struc:ty, $idx:expr, $field:ident, $name:expr, nofin) => {
|
||||||
impl Kind for $struc {
|
impl Kind for $struc {
|
||||||
const INDEX: usize = $idx;
|
const INDEX: usize = $idx;
|
||||||
fn from_program_mut(program: &mut UProgram) -> &mut Vec<Option<Self>> {
|
fn from_program_mut(program: &mut UProgram) -> &mut Vec<Option<Self>> {
|
||||||
@@ -117,7 +119,7 @@ macro_rules! impl_kind {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_kind!(UFunc, 0, fns, "func");
|
impl_kind!(UFunc, 0, fns, "func", nofin);
|
||||||
impl_kind!(UVar, 1, vars, "var");
|
impl_kind!(UVar, 1, vars, "var");
|
||||||
impl_kind!(UStruct, 2, structs, "struct");
|
impl_kind!(UStruct, 2, structs, "struct");
|
||||||
impl_kind!(UGeneric, 3, types, "type");
|
impl_kind!(UGeneric, 3, types, "type");
|
||||||
@@ -130,12 +132,26 @@ pub type StructID = ID<UStruct>;
|
|||||||
pub type DataID = ID<UData>;
|
pub type DataID = ID<UData>;
|
||||||
pub type GenericID = ID<UGeneric>;
|
pub type GenericID = ID<UGeneric>;
|
||||||
|
|
||||||
pub trait Kind {
|
impl Finish for UFunc {
|
||||||
const INDEX: usize;
|
fn finish(p: &mut UProgram, id: ID<Self>) {
|
||||||
fn from_program_mut(program: &mut UProgram) -> &mut Vec<Option<Self>>
|
let var = p.def_searchable(
|
||||||
where
|
p.names.name(id).to_string(),
|
||||||
Self: Sized;
|
Some(UVar {
|
||||||
fn from_program(program: &UProgram) -> &Vec<Option<Self>>
|
parent: None,
|
||||||
where
|
ty: Type::Placeholder,
|
||||||
Self: Sized;
|
}),
|
||||||
|
p.origins.get(id),
|
||||||
|
);
|
||||||
|
p.fn_var.insert(id, var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Kind: Sized {
|
||||||
|
const INDEX: usize;
|
||||||
|
fn from_program_mut(program: &mut UProgram) -> &mut Vec<Option<Self>>;
|
||||||
|
fn from_program(program: &UProgram) -> &Vec<Option<Self>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Finish: Sized {
|
||||||
|
fn finish(program: &mut UProgram, id: ID<Self>);
|
||||||
}
|
}
|
||||||
|
|||||||
109
src/ir/upper/maps.rs
Normal file
109
src/ir/upper/maps.rs
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
use super::{FnID, Kind, Origin, VarID, NAMED_KINDS};
|
||||||
|
use crate::ir::ID;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
pub struct OriginMap {
|
||||||
|
origins: [Vec<Origin>; NAMED_KINDS],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OriginMap {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
origins: core::array::from_fn(|_| Vec::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn get<K: Kind>(&self, id: ID<K>) -> Origin {
|
||||||
|
self.origins[K::INDEX][id.0]
|
||||||
|
}
|
||||||
|
pub fn push<K: Kind>(&mut self, origin: Origin) {
|
||||||
|
self.origins[K::INDEX].push(origin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NameMap {
|
||||||
|
names: [Vec<String>; NAMED_KINDS],
|
||||||
|
inv_names: [HashMap<String, usize>; NAMED_KINDS],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NameMap {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
names: core::array::from_fn(|_| Vec::new()),
|
||||||
|
inv_names: core::array::from_fn(|_| HashMap::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn name<K: Kind>(&self, id: ID<K>) -> &str {
|
||||||
|
&self.names[K::INDEX][id.0]
|
||||||
|
}
|
||||||
|
pub fn id<K: Kind>(&self, name: &str) -> Option<ID<K>> {
|
||||||
|
Some(ID::new(*self.inv_names[K::INDEX].get(name)?))
|
||||||
|
}
|
||||||
|
pub fn push<K: Kind>(&mut self, name: String) {
|
||||||
|
self.inv_names[K::INDEX].insert(name.clone(), self.names[K::INDEX].len());
|
||||||
|
self.names[K::INDEX].push(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FnVarMap {
|
||||||
|
vtf: HashMap<VarID, FnID>,
|
||||||
|
ftv: Vec<VarID>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FnVarMap {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
vtf: HashMap::new(),
|
||||||
|
ftv: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn insert(&mut self, f: FnID, v: VarID) {
|
||||||
|
self.vtf.insert(v, f);
|
||||||
|
self.ftv.push(v);
|
||||||
|
}
|
||||||
|
pub fn var(&self, f: FnID) -> VarID {
|
||||||
|
self.ftv[f.0]
|
||||||
|
}
|
||||||
|
pub fn fun(&self, v: VarID) -> Option<FnID> {
|
||||||
|
self.vtf.get(&v).copied()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct Ident {
|
||||||
|
id: usize,
|
||||||
|
kind: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K: Kind> From<ID<K>> for Ident {
|
||||||
|
fn from(id: ID<K>) -> Self {
|
||||||
|
Self {
|
||||||
|
id: id.0,
|
||||||
|
kind: K::INDEX,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this isn't really a map... but also keeps track of "side data"
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct Idents {
|
||||||
|
pub latest: Ident,
|
||||||
|
pub kinds: [Option<usize>; NAMED_KINDS],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Idents {
|
||||||
|
pub fn new(latest: Ident) -> Self {
|
||||||
|
let mut s = Self {
|
||||||
|
latest,
|
||||||
|
kinds: [None; NAMED_KINDS],
|
||||||
|
};
|
||||||
|
s.insert(latest);
|
||||||
|
s
|
||||||
|
}
|
||||||
|
pub fn insert(&mut self, i: Ident) {
|
||||||
|
self.latest = i;
|
||||||
|
self.kinds[i.kind] = Some(i.id);
|
||||||
|
}
|
||||||
|
pub fn get<K: Kind>(&self) -> Option<ID<K>> {
|
||||||
|
self.kinds[K::INDEX].map(|i| i.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,8 +5,11 @@ mod program;
|
|||||||
mod validate;
|
mod validate;
|
||||||
mod error;
|
mod error;
|
||||||
mod inst;
|
mod inst;
|
||||||
|
mod maps;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use maps::*;
|
||||||
|
pub use maps::Idents;
|
||||||
pub use kind::*;
|
pub use kind::*;
|
||||||
pub use instr::*;
|
pub use instr::*;
|
||||||
pub use ty::*;
|
pub use ty::*;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use std::{collections::HashMap, fmt::Debug};
|
use super::*;
|
||||||
|
use std::collections::HashMap;
|
||||||
use super::{inst::VarInst, *};
|
|
||||||
|
|
||||||
pub struct UProgram {
|
pub struct UProgram {
|
||||||
pub fns: Vec<Option<UFunc>>,
|
pub fns: Vec<Option<UFunc>>,
|
||||||
@@ -8,39 +7,14 @@ pub struct UProgram {
|
|||||||
pub structs: Vec<Option<UStruct>>,
|
pub structs: Vec<Option<UStruct>>,
|
||||||
pub types: Vec<Option<UGeneric>>,
|
pub types: Vec<Option<UGeneric>>,
|
||||||
pub data: Vec<Option<UData>>,
|
pub data: Vec<Option<UData>>,
|
||||||
pub start: Option<FnID>,
|
|
||||||
pub names: NameMap,
|
pub names: NameMap,
|
||||||
|
pub origins: OriginMap,
|
||||||
// todo: these feel weird raw
|
// todo: these feel weird raw
|
||||||
pub fn_map: HashMap<VarID, FnID>,
|
pub fn_var: FnVarMap,
|
||||||
pub inv_fn_map: Vec<VarID>,
|
|
||||||
pub temp: usize,
|
pub temp: usize,
|
||||||
pub name_stack: Vec<HashMap<String, Idents>>,
|
pub name_stack: Vec<HashMap<String, Idents>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct NameMap {
|
|
||||||
names: [Vec<String>; NAMED_KINDS],
|
|
||||||
inv_names: [HashMap<String, usize>; NAMED_KINDS],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NameMap {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
names: core::array::from_fn(|_| Vec::new()),
|
|
||||||
inv_names: core::array::from_fn(|_| HashMap::new()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn get<K: Kind>(&self, id: ID<K>) -> &str {
|
|
||||||
&self.names[K::INDEX][id.0]
|
|
||||||
}
|
|
||||||
pub fn lookup<K: Kind>(&self, name: &str) -> Option<ID<K>> {
|
|
||||||
Some(ID::new(*self.inv_names[K::INDEX].get(name)?))
|
|
||||||
}
|
|
||||||
pub fn push<K: Kind>(&mut self, name: String) {
|
|
||||||
self.inv_names[K::INDEX].insert(name.clone(), self.names[K::INDEX].len());
|
|
||||||
self.names[K::INDEX].push(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UProgram {
|
impl UProgram {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -49,10 +23,9 @@ impl UProgram {
|
|||||||
structs: Vec::new(),
|
structs: Vec::new(),
|
||||||
types: Vec::new(),
|
types: Vec::new(),
|
||||||
data: Vec::new(),
|
data: Vec::new(),
|
||||||
start: None,
|
|
||||||
names: NameMap::new(),
|
names: NameMap::new(),
|
||||||
fn_map: HashMap::new(),
|
origins: OriginMap::new(),
|
||||||
inv_fn_map: Vec::new(),
|
fn_var: FnVarMap::new(),
|
||||||
temp: 0,
|
temp: 0,
|
||||||
name_stack: vec![HashMap::new()],
|
name_stack: vec![HashMap::new()],
|
||||||
}
|
}
|
||||||
@@ -87,7 +60,7 @@ impl UProgram {
|
|||||||
.unwrap_or_else(|| panic!("{id:?} not defined yet!"))
|
.unwrap_or_else(|| panic!("{id:?} not defined yet!"))
|
||||||
}
|
}
|
||||||
pub fn get_fn_var(&self, id: VarID) -> Option<&UFunc> {
|
pub fn get_fn_var(&self, id: VarID) -> Option<&UFunc> {
|
||||||
self.fns[self.fn_map.get(&id)?.0].as_ref()
|
self.fns[self.fn_var.fun(id)?.0].as_ref()
|
||||||
}
|
}
|
||||||
pub fn temp_subvar(&mut self, origin: Origin, ty: Type, parent: FieldRef) -> VarInst {
|
pub fn temp_subvar(&mut self, origin: Origin, ty: Type, parent: FieldRef) -> VarInst {
|
||||||
self.temp_var_inner(origin, ty, Some(parent))
|
self.temp_var_inner(origin, ty, Some(parent))
|
||||||
@@ -99,7 +72,8 @@ impl UProgram {
|
|||||||
fn temp_var_inner(&mut self, origin: Origin, ty: Type, parent: Option<FieldRef>) -> VarInst {
|
fn temp_var_inner(&mut self, origin: Origin, ty: Type, parent: Option<FieldRef>) -> VarInst {
|
||||||
let v = self.def(
|
let v = self.def(
|
||||||
format!("temp{}", self.temp),
|
format!("temp{}", self.temp),
|
||||||
Some(UVar { parent, origin, ty }),
|
Some(UVar { parent, ty }),
|
||||||
|
origin,
|
||||||
);
|
);
|
||||||
self.temp += 1;
|
self.temp += 1;
|
||||||
VarInst {
|
VarInst {
|
||||||
@@ -112,16 +86,23 @@ impl UProgram {
|
|||||||
K::from_program_mut(self)[id.0] = Some(k);
|
K::from_program_mut(self)[id.0] = Some(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn def<K: Kind>(&mut self, name: String, k: Option<K>) -> ID<K> {
|
pub fn def<K: Kind + Finish>(&mut self, name: String, k: Option<K>, origin: Origin) -> ID<K> {
|
||||||
self.names.push::<K>(name);
|
self.names.push::<K>(name);
|
||||||
|
self.origins.push::<K>(origin);
|
||||||
let vec = K::from_program_mut(self);
|
let vec = K::from_program_mut(self);
|
||||||
let id = ID::new(vec.len());
|
let id = ID::new(vec.len());
|
||||||
vec.push(k);
|
vec.push(k);
|
||||||
|
K::finish(self, id);
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn def_searchable<K: Kind>(&mut self, name: String, k: Option<K>) -> ID<K> {
|
pub fn def_searchable<K: Kind + Finish>(
|
||||||
let id = self.def(name.clone(), k);
|
&mut self,
|
||||||
|
name: String,
|
||||||
|
k: Option<K>,
|
||||||
|
origin: Origin,
|
||||||
|
) -> ID<K> {
|
||||||
|
let id = self.def(name.clone(), k, origin);
|
||||||
self.name_on_stack(id, name);
|
self.name_on_stack(id, name);
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
@@ -135,7 +116,7 @@ impl UProgram {
|
|||||||
if let Type::Generic { id } = field.ty {
|
if let Type::Generic { id } = field.ty {
|
||||||
for (i, g) in struc.generics.iter().enumerate() {
|
for (i, g) in struc.generics.iter().enumerate() {
|
||||||
if *g == id {
|
if *g == id {
|
||||||
return Some(&args[i])
|
return Some(&args[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -146,7 +127,7 @@ impl UProgram {
|
|||||||
let mut str = String::new();
|
let mut str = String::new();
|
||||||
match ty {
|
match ty {
|
||||||
Type::Struct { id: base, args } => {
|
Type::Struct { id: base, args } => {
|
||||||
str += self.names.get(*base);
|
str += self.names.name(*base);
|
||||||
if let Some(arg) = args.first() {
|
if let Some(arg) = args.first() {
|
||||||
str = str + "<" + &self.type_name(arg);
|
str = str + "<" + &self.type_name(arg);
|
||||||
}
|
}
|
||||||
@@ -173,7 +154,7 @@ impl UProgram {
|
|||||||
}
|
}
|
||||||
Type::Error => str += "{error}",
|
Type::Error => str += "{error}",
|
||||||
Type::Infer => str += "{inferred}",
|
Type::Infer => str += "{inferred}",
|
||||||
Type::Generic { id } => str += self.names.get(*id),
|
Type::Generic { id } => str += self.names.name(*id),
|
||||||
Type::Bits(size) => str += &format!("b{}", size),
|
Type::Bits(size) => str += &format!("b{}", size),
|
||||||
Type::Array(t, len) => str += &format!("[{}; {len}]", self.type_name(t)),
|
Type::Array(t, len) => str += &format!("[{}; {len}]", self.type_name(t)),
|
||||||
Type::Unit => str += "()",
|
Type::Unit => str += "()",
|
||||||
@@ -206,42 +187,3 @@ impl UProgram {
|
|||||||
.map(|(i, x)| (ID::new(i), x))
|
.map(|(i, x)| (ID::new(i), x))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub struct Ident {
|
|
||||||
id: usize,
|
|
||||||
kind: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<K: Kind> From<ID<K>> for Ident {
|
|
||||||
fn from(id: ID<K>) -> Self {
|
|
||||||
Self {
|
|
||||||
id: id.0,
|
|
||||||
kind: K::INDEX,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub struct Idents {
|
|
||||||
pub latest: Ident,
|
|
||||||
pub kinds: [Option<usize>; NAMED_KINDS],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Idents {
|
|
||||||
fn new(latest: Ident) -> Self {
|
|
||||||
let mut s = Self {
|
|
||||||
latest,
|
|
||||||
kinds: [None; NAMED_KINDS],
|
|
||||||
};
|
|
||||||
s.insert(latest);
|
|
||||||
s
|
|
||||||
}
|
|
||||||
fn insert(&mut self, i: Ident) {
|
|
||||||
self.latest = i;
|
|
||||||
self.kinds[i.kind] = Some(i.id);
|
|
||||||
}
|
|
||||||
pub fn get<K: Kind>(&self) -> Option<ID<K>> {
|
|
||||||
self.kinds[K::INDEX].map(|i| i.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,36 +5,43 @@ use crate::common::{CompilerMsg, CompilerOutput, FileSpan};
|
|||||||
impl UProgram {
|
impl UProgram {
|
||||||
pub fn validate(&self) -> CompilerOutput {
|
pub fn validate(&self) -> CompilerOutput {
|
||||||
let mut output = CompilerOutput::new();
|
let mut output = CompilerOutput::new();
|
||||||
for f in self.fns.iter().flatten() {
|
for (id, f) in self.iter_fns() {
|
||||||
self.validate_fn(&f.instructions, f.origin, &f.ret, &mut output, true, false);
|
self.validate_fn(
|
||||||
|
&f.instructions,
|
||||||
|
self.origins.get(id),
|
||||||
|
&f.ret,
|
||||||
|
&mut output,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
for (id, var) in self.iter_vars() {
|
for (id, var) in self.iter_vars() {
|
||||||
if var.ty == Type::Error {
|
if var.ty == Type::Error {
|
||||||
output.err(CompilerMsg {
|
output.err(CompilerMsg {
|
||||||
msg: format!("Var {:?} is error type!", id),
|
msg: format!("Var {:?} is error type!", id),
|
||||||
spans: vec![var.origin],
|
spans: vec![self.origins.get(id)],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if var.ty == Type::Infer {
|
if var.ty == Type::Infer {
|
||||||
output.err(CompilerMsg {
|
output.err(CompilerMsg {
|
||||||
msg: format!("Var {:?} cannot be inferred", id),
|
msg: format!("Var {:?} cannot be inferred", id),
|
||||||
spans: vec![var.origin],
|
spans: vec![self.origins.get(id)],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if var.ty == Type::Placeholder {
|
if var.ty == Type::Placeholder {
|
||||||
output.err(CompilerMsg {
|
output.err(CompilerMsg {
|
||||||
msg: format!("Var {:?} still placeholder!", id),
|
msg: format!("Var {:?} still placeholder!", id),
|
||||||
spans: vec![var.origin],
|
spans: vec![self.origins.get(id)],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if let Some(parent) = &var.parent {
|
if let Some(parent) = &var.parent {
|
||||||
let pty = &self.get(parent.var).unwrap().ty;
|
let pty = &self.get(parent.var).unwrap().ty;
|
||||||
if let Some(ft) = self.field_type(pty, &parent.field) {
|
if let Some(ft) = self.field_type(pty, &parent.field) {
|
||||||
output.check_assign(self, &var.ty, ft, var.origin);
|
output.check_assign(self, &var.ty, ft, self.origins.get(id));
|
||||||
} else {
|
} else {
|
||||||
output.err(CompilerMsg {
|
output.err(CompilerMsg {
|
||||||
msg: format!("invalid parent!"),
|
msg: format!("invalid parent!"),
|
||||||
spans: vec![var.origin],
|
spans: vec![self.origins.get(id)],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,14 +15,7 @@ impl Node<PVarDef> {
|
|||||||
None => Type::Infer,
|
None => Type::Infer,
|
||||||
};
|
};
|
||||||
Some(VarInst {
|
Some(VarInst {
|
||||||
id: program.def_searchable(
|
id: program.def_searchable(name, Some(UVar { ty, parent: None }), self.span),
|
||||||
name,
|
|
||||||
Some(UVar {
|
|
||||||
ty,
|
|
||||||
parent: None,
|
|
||||||
origin: self.span,
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
span: self.span,
|
span: self.span,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ impl FnLowerable for PExpr {
|
|||||||
format!("string \"{}\"", s.replace("\n", "\\n")),
|
format!("string \"{}\"", s.replace("\n", "\\n")),
|
||||||
Some(UData {
|
Some(UData {
|
||||||
ty: Type::Bits(8).arr(data.len() as u32),
|
ty: Type::Bits(8).arr(data.len() as u32),
|
||||||
origin: l.span,
|
|
||||||
content: data,
|
content: data,
|
||||||
}),
|
}),
|
||||||
|
l.span,
|
||||||
);
|
);
|
||||||
ctx.push(UInstruction::LoadSlice { dest, src });
|
ctx.push(UInstruction::LoadSlice { dest, src });
|
||||||
dest
|
dest
|
||||||
@@ -30,9 +30,9 @@ impl FnLowerable for PExpr {
|
|||||||
format!("char '{c}'"),
|
format!("char '{c}'"),
|
||||||
Some(UData {
|
Some(UData {
|
||||||
ty,
|
ty,
|
||||||
origin: l.span,
|
|
||||||
content: c.to_string().as_bytes().to_vec(),
|
content: c.to_string().as_bytes().to_vec(),
|
||||||
}),
|
}),
|
||||||
|
l.span,
|
||||||
);
|
);
|
||||||
ctx.push(UInstruction::LoadData { dest, src });
|
ctx.push(UInstruction::LoadData { dest, src });
|
||||||
dest
|
dest
|
||||||
@@ -45,9 +45,9 @@ impl FnLowerable for PExpr {
|
|||||||
format!("num {n:?}"),
|
format!("num {n:?}"),
|
||||||
Some(UData {
|
Some(UData {
|
||||||
ty,
|
ty,
|
||||||
origin: l.span,
|
|
||||||
content: n.whole.parse::<i64>().unwrap().to_le_bytes().to_vec(),
|
content: n.whole.parse::<i64>().unwrap().to_le_bytes().to_vec(),
|
||||||
}),
|
}),
|
||||||
|
l.span
|
||||||
);
|
);
|
||||||
ctx.push(UInstruction::LoadData { dest, src });
|
ctx.push(UInstruction::LoadData { dest, src });
|
||||||
dest
|
dest
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
use super::{CompilerMsg, CompilerOutput, FileSpan, FnLowerable, Node, PFunction};
|
use super::{CompilerMsg, CompilerOutput, FileSpan, FnLowerable, Node, PFunction};
|
||||||
use crate::{
|
use crate::{
|
||||||
ir::{
|
ir::{FieldRef, FnID, Idents, Type, UFunc, UInstrInst, UInstruction, UProgram, UVar, VarInst},
|
||||||
FieldRef, FnID, Idents, InstrIter, Type, UFunc, UInstrInst, UInstruction, UProgram, UVar,
|
|
||||||
VarInst,
|
|
||||||
},
|
|
||||||
parser,
|
parser,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -22,17 +19,7 @@ impl PFunction {
|
|||||||
pub fn lower_name(&self, p: &mut UProgram) -> Option<FnID> {
|
pub fn lower_name(&self, p: &mut UProgram) -> Option<FnID> {
|
||||||
let header = self.header.as_ref()?;
|
let header = self.header.as_ref()?;
|
||||||
let name = header.name.as_ref()?;
|
let name = header.name.as_ref()?;
|
||||||
let id = p.def_searchable(name.to_string(), None);
|
let id = p.def_searchable(name.to_string(), None, self.header.span);
|
||||||
let var = p.def_searchable(
|
|
||||||
name.to_string(),
|
|
||||||
Some(UVar {
|
|
||||||
parent: None,
|
|
||||||
ty: Type::Placeholder,
|
|
||||||
origin: self.header.span,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
p.fn_map.insert(var, id);
|
|
||||||
p.inv_fn_map.push(var);
|
|
||||||
Some(id)
|
Some(id)
|
||||||
}
|
}
|
||||||
pub fn lower(&self, id: FnID, p: &mut UProgram, output: &mut CompilerOutput) {
|
pub fn lower(&self, id: FnID, p: &mut UProgram, output: &mut CompilerOutput) {
|
||||||
@@ -63,15 +50,13 @@ impl PFunction {
|
|||||||
span: src.span,
|
span: src.span,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let origin = self.header.span;
|
|
||||||
let instructions = ctx.instructions;
|
let instructions = ctx.instructions;
|
||||||
let f = UFunc {
|
let f = UFunc {
|
||||||
origin,
|
|
||||||
args,
|
args,
|
||||||
ret,
|
ret,
|
||||||
instructions,
|
instructions,
|
||||||
};
|
};
|
||||||
p.expect_mut(p.inv_fn_map[id.0]).ty = f.ty(p);
|
p.expect_mut(p.fn_var.var(id)).ty = f.ty(p);
|
||||||
p.write(id, f)
|
p.write(id, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ impl PStruct {
|
|||||||
let generics = self
|
let generics = self
|
||||||
.generics
|
.generics
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|a| a.as_ref()?.lower(p))
|
.flat_map(|a| a.lower(p))
|
||||||
.collect();
|
.collect();
|
||||||
let fields = match &self.fields {
|
let fields = match &self.fields {
|
||||||
PStructFields::Named(nodes) => nodes
|
PStructFields::Named(nodes) => nodes
|
||||||
@@ -75,14 +75,7 @@ impl PStruct {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(name, ty)| (name, StructField { ty }))
|
.map(|(name, ty)| (name, StructField { ty }))
|
||||||
.collect();
|
.collect();
|
||||||
p.write(
|
p.write(id, UStruct { generics, fields });
|
||||||
id,
|
|
||||||
UStruct {
|
|
||||||
origin: span,
|
|
||||||
generics,
|
|
||||||
fields,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
p.pop();
|
p.pop();
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
@@ -90,8 +83,9 @@ impl PStruct {
|
|||||||
|
|
||||||
impl Node<PStruct> {
|
impl Node<PStruct> {
|
||||||
pub fn lower_name(&self, p: &mut UProgram) -> Option<StructID> {
|
pub fn lower_name(&self, p: &mut UProgram) -> Option<StructID> {
|
||||||
let name = self.as_ref()?.name.as_ref()?.to_string();
|
let s = self.as_ref()?;
|
||||||
let id = p.def_searchable(name.to_string(), None);
|
let name = s.name.as_ref()?.to_string();
|
||||||
|
let id = p.def_searchable(name.to_string(), None, s.name.span);
|
||||||
Some(id)
|
Some(id)
|
||||||
}
|
}
|
||||||
pub fn lower(&self, id: StructID, p: &mut UProgram, output: &mut CompilerOutput) {
|
pub fn lower(&self, id: StructID, p: &mut UProgram, output: &mut CompilerOutput) {
|
||||||
|
|||||||
@@ -43,11 +43,10 @@ impl PType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PGenericDef {
|
impl Node<PGenericDef> {
|
||||||
pub fn lower(&self, p: &mut UProgram) -> Option<GenericID> {
|
pub fn lower(&self, p: &mut UProgram) -> Option<GenericID> {
|
||||||
let Some(name) = self.name.as_ref() else {
|
let s = self.as_ref()?;
|
||||||
return None;
|
let name = s.name.as_ref()?;
|
||||||
};
|
Some(p.def_searchable(name.to_string(), Some(UGeneric {}), self.span))
|
||||||
Some(p.def_searchable(name.to_string(), Some(UGeneric {})))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user