uh oh, I need to actually switch to struct subvars and resolve pointer variables
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::ir::{AsmBlockArgType, Size, StructTy, SymbolSpace, UFunc, UInstrInst, VarOffset};
|
use crate::ir::{AsmBlockArgType, Size, StructTy, SymbolSpace, Type, UFunc, UInstrInst, VarOffset};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
IRLFunction, LInstruction, Len, Symbol, SymbolSpaceBuilder, Type, UInstruction, UProgram, VarID,
|
IRLFunction, LInstruction, Len, Symbol, SymbolSpaceBuilder, UInstruction, UProgram, VarID,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct LProgram {
|
pub struct LProgram {
|
||||||
@@ -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
|
||||||
.id::<UFunc>(&["crate".to_string()])
|
.id::<UFunc>(&[], "crate")
|
||||||
.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);
|
||||||
@@ -356,17 +356,22 @@ impl<'a> LFunctionBuilder<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LFunctionBuilderData<'_> {
|
impl LFunctionBuilderData<'_> {
|
||||||
pub fn var_offset(&mut self, p: &UProgram, var: VarID) -> Option<VarOffset> {
|
pub fn var_offset(&mut self, p: &UProgram, mut var: VarID) -> Option<VarOffset> {
|
||||||
let mut current = VarOffset { id: var, offset: 0 };
|
let mut path = Vec::new();
|
||||||
while let Type::Member(parent) = &p.get(current.id)?.ty {
|
while let Type::Field(parent) = &p.get(var)?.ty {
|
||||||
current.id = parent.parent;
|
var = parent.parent;
|
||||||
// ... should it be set to 0 if not? what does that even mean??
|
path.push(&parent.name);
|
||||||
// "the field of this struct is a reference to another variable" ????
|
|
||||||
if let Type::Struct(sty) = &p.get(parent.parent)?.ty {
|
|
||||||
current.offset += self.field_offset(p, sty, &parent.name)?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Some(current)
|
let mut ty = &p.get(var)?.ty;
|
||||||
|
let mut offset = 0;
|
||||||
|
while let Type::Struct(sty) = ty {
|
||||||
|
let Some(name) = path.pop() else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
offset += self.field_offset(p, sty, &name)?;
|
||||||
|
ty = p.struct_field_type(sty, name).expect("bad field");
|
||||||
|
}
|
||||||
|
Some(VarOffset { id: var, offset })
|
||||||
}
|
}
|
||||||
pub fn addr_size(&self) -> Size {
|
pub fn addr_size(&self) -> Size {
|
||||||
64
|
64
|
||||||
@@ -425,7 +430,7 @@ impl LFunctionBuilderData<'_> {
|
|||||||
|
|
||||||
pub fn size_of_type(&mut self, p: &UProgram, ty: &Type) -> Option<Size> {
|
pub fn size_of_type(&mut self, p: &UProgram, ty: &Type) -> Option<Size> {
|
||||||
// TODO: target matters
|
// TODO: target matters
|
||||||
Some(match ty {
|
Some(match p.follow_type(ty)? {
|
||||||
Type::Bits(b) => *b,
|
Type::Bits(b) => *b,
|
||||||
Type::Struct(ty) => self.struct_inst(p, ty).size,
|
Type::Struct(ty) => self.struct_inst(p, ty).size,
|
||||||
Type::Generic { id } => return None,
|
Type::Generic { id } => return None,
|
||||||
@@ -433,22 +438,8 @@ impl LFunctionBuilderData<'_> {
|
|||||||
Type::Ref(_) => self.addr_size(),
|
Type::Ref(_) => self.addr_size(),
|
||||||
Type::Array(ty, len) => self.size_of_type(p, ty)? * len,
|
Type::Array(ty, len) => self.size_of_type(p, ty)? * len,
|
||||||
Type::Slice(_) => self.addr_size() * 2,
|
Type::Slice(_) => self.addr_size() * 2,
|
||||||
Type::Infer => return None,
|
|
||||||
Type::Error => return None,
|
|
||||||
Type::Unit => 0,
|
Type::Unit => 0,
|
||||||
Type::Placeholder => return None,
|
_ => return None,
|
||||||
Type::Module(_) => return None,
|
|
||||||
Type::Member(m) => {
|
|
||||||
let pty = &p.expect(m.parent).ty;
|
|
||||||
let ty = match pty {
|
|
||||||
Type::Struct(ty) => self.struct_inst(p, ty).ty(&m.name)?,
|
|
||||||
Type::Module(path) => p.path_ty(path)?,
|
|
||||||
Type::Member(_) => return self.size_of_type(p, pty),
|
|
||||||
_ => return None,
|
|
||||||
}
|
|
||||||
.clone();
|
|
||||||
self.size_of_type(p, &ty)?
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,10 +38,9 @@ impl NameTree {
|
|||||||
let first = path.first()?;
|
let first = path.first()?;
|
||||||
self.children.get(first)?.get(&path[1..])
|
self.children.get(first)?.get(&path[1..])
|
||||||
}
|
}
|
||||||
pub fn id<K: Kind>(&self, path: &[String]) -> Option<ID<K>> {
|
pub fn id<K: Kind>(&self, path: &[String], name: &str) -> Option<ID<K>> {
|
||||||
let last = path.last()?;
|
self.get(&path)?.ids[K::INDEX]
|
||||||
self.get(&path[..path.len() - 1])?.ids[K::INDEX]
|
.get(name)
|
||||||
.get(last)
|
|
||||||
.copied()
|
.copied()
|
||||||
.map(ID::new)
|
.map(ID::new)
|
||||||
}
|
}
|
||||||
@@ -82,8 +81,8 @@ impl NameMap {
|
|||||||
}
|
}
|
||||||
path
|
path
|
||||||
}
|
}
|
||||||
pub fn id<K: Kind>(&self, path: &[String]) -> Option<ID<K>> {
|
pub fn id<K: Kind>(&self, path: &[String], name: &str) -> Option<ID<K>> {
|
||||||
Some(self.tree.id(path)?)
|
Some(self.tree.id(path, name)?)
|
||||||
}
|
}
|
||||||
pub fn push<K: Kind>(&mut self, path: &[String]) {
|
pub fn push<K: Kind>(&mut self, path: &[String]) {
|
||||||
let id = self.names[K::INDEX].len();
|
let id = self.names[K::INDEX].len();
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
use crate::common::{CompilerMsg, CompilerOutput, FileSpan};
|
use crate::common::{CompilerMsg, CompilerOutput, FileSpan};
|
||||||
|
|
||||||
use super::{Type, UProgram};
|
use super::{UProgram, Type};
|
||||||
|
|
||||||
impl CompilerOutput {
|
impl CompilerOutput {
|
||||||
pub fn check_assign(&mut self, p: &UProgram, src: &Type, dest: &Type, span: FileSpan) {
|
pub fn check_assign(&mut self, p: &UProgram, src: &Type, dest: &Type, span: FileSpan) {
|
||||||
// TODO: spans
|
// TODO: spans
|
||||||
if src != dest {
|
if src != dest {
|
||||||
if !src.is_real() || !dest.is_real() {
|
if !src.is_resolved() || !dest.is_resolved() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.err(CompilerMsg {
|
self.err(CompilerMsg {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ pub struct VarInst {
|
|||||||
pub span: FileSpan,
|
pub span: FileSpan,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct UInstrInst {
|
pub struct UInstrInst {
|
||||||
pub i: UInstruction,
|
pub i: UInstruction,
|
||||||
pub span: FileSpan,
|
pub span: FileSpan,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use std::{collections::HashMap, fmt::Write};
|
|||||||
use super::{arch::riscv64::RV64Instruction, inst::VarInst, DataID, FnID, UFunc, UInstrInst};
|
use super::{arch::riscv64::RV64Instruction, inst::VarInst, DataID, FnID, UFunc, UInstrInst};
|
||||||
use crate::{compiler::arch::riscv::Reg, util::Padder};
|
use crate::{compiler::arch::riscv::Reg, util::Padder};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum UInstruction {
|
pub enum UInstruction {
|
||||||
Mv {
|
Mv {
|
||||||
dest: VarInst,
|
dest: VarInst,
|
||||||
@@ -51,14 +52,14 @@ pub enum UInstruction {
|
|||||||
Continue,
|
Continue,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct AsmBlockArg {
|
pub struct AsmBlockArg {
|
||||||
pub var: VarInst,
|
pub var: VarInst,
|
||||||
pub reg: Reg,
|
pub reg: Reg,
|
||||||
pub ty: AsmBlockArgType,
|
pub ty: AsmBlockArgType,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum AsmBlockArgType {
|
pub enum AsmBlockArgType {
|
||||||
In,
|
In,
|
||||||
Out,
|
Out,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use std::{collections::HashMap, fmt::Debug};
|
use std::{collections::HashMap, fmt::Debug};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct UFunc {
|
pub struct UFunc {
|
||||||
pub args: Vec<VarID>,
|
pub args: Vec<VarID>,
|
||||||
pub ret: Type,
|
pub ret: Type,
|
||||||
@@ -128,7 +129,7 @@ pub type GenericID = ID<UGeneric>;
|
|||||||
impl Finish for UFunc {
|
impl Finish for UFunc {
|
||||||
fn finish(p: &mut UProgram, id: ID<Self>, name: &str) {
|
fn finish(p: &mut UProgram, id: ID<Self>, name: &str) {
|
||||||
let var = p.def_searchable(
|
let var = p.def_searchable(
|
||||||
name.to_string(),
|
name,
|
||||||
Some(UVar {
|
Some(UVar {
|
||||||
ty: Type::Placeholder,
|
ty: Type::Placeholder,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ pub struct UProgram {
|
|||||||
pub names: NameMap,
|
pub names: NameMap,
|
||||||
pub origins: OriginMap,
|
pub origins: OriginMap,
|
||||||
pub fn_var: FnVarMap,
|
pub fn_var: FnVarMap,
|
||||||
|
// utils for creation
|
||||||
pub path: Vec<String>,
|
pub path: Vec<String>,
|
||||||
pub name_stack: Vec<HashMap<String, Idents>>,
|
pub name_stack: Vec<HashMap<String, Idents>>,
|
||||||
pub temp: usize,
|
pub temp: usize,
|
||||||
@@ -29,10 +30,14 @@ impl UProgram {
|
|||||||
origins: OriginMap::new(),
|
origins: OriginMap::new(),
|
||||||
fn_var: FnVarMap::new(),
|
fn_var: FnVarMap::new(),
|
||||||
path: Vec::new(),
|
path: Vec::new(),
|
||||||
name_stack: vec![HashMap::new()],
|
name_stack: Vec::new(),
|
||||||
temp: 0,
|
temp: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn set_module(&mut self, path: Vec<String>) {
|
||||||
|
self.path = path;
|
||||||
|
self.name_stack = vec![HashMap::new()];
|
||||||
|
}
|
||||||
pub fn push(&mut self) {
|
pub fn push(&mut self) {
|
||||||
self.name_stack.push(HashMap::new());
|
self.name_stack.push(HashMap::new());
|
||||||
}
|
}
|
||||||
@@ -72,12 +77,16 @@ impl UProgram {
|
|||||||
self.fns[self.fn_var.fun(id)?.0].as_ref()
|
self.fns[self.fn_var.fun(id)?.0].as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn temp_var(&mut self, origin: Origin, ty: Type) -> VarInst {
|
pub fn temp_var(&mut self, origin: Origin, ty: impl Into<Type>) -> VarInst {
|
||||||
self.temp_var_inner(origin, ty)
|
self.temp_var_inner(origin, ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn temp_var_inner(&mut self, origin: Origin, ty: Type) -> VarInst {
|
fn temp_var_inner(&mut self, origin: Origin, ty: impl Into<Type>) -> VarInst {
|
||||||
let v = self.def(&format!("temp{}", self.temp), Some(UVar { ty }), origin);
|
let v = self.def(
|
||||||
|
&format!("temp{}", self.temp),
|
||||||
|
Some(UVar { ty: ty.into() }),
|
||||||
|
origin,
|
||||||
|
);
|
||||||
self.temp += 1;
|
self.temp += 1;
|
||||||
VarInst {
|
VarInst {
|
||||||
id: v,
|
id: v,
|
||||||
@@ -110,48 +119,86 @@ impl UProgram {
|
|||||||
|
|
||||||
pub fn def_searchable<K: Kind + Finish>(
|
pub fn def_searchable<K: Kind + Finish>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: String,
|
name: &str,
|
||||||
k: Option<K>,
|
k: Option<K>,
|
||||||
origin: Origin,
|
origin: Origin,
|
||||||
) -> ID<K> {
|
) -> ID<K> {
|
||||||
let id = self.def(&name, k, origin);
|
let id = self.def(&name, k, origin);
|
||||||
self.name_on_stack(id, name);
|
self.name_on_stack(id, name.to_string());
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ref_ty<'a>(&'a self, mem: &MemberRef) -> Option<&'a Type> {
|
pub fn struct_field_type<'a>(&'a self, sty: &'a StructTy, field: &str) -> Option<&'a Type> {
|
||||||
self.follow_ref(mem).and_then(|r| Some(&self.get(r)?.ty))
|
let struc = self.get(sty.id)?;
|
||||||
}
|
let field = struc.fields.get(field)?;
|
||||||
|
if let Type::Generic { id } = field.ty {
|
||||||
pub fn follow_ref<'a>(&'a self, mem: &MemberRef) -> Option<VarID> {
|
for (i, g) in struc.generics.iter().enumerate() {
|
||||||
let parent = self.get(mem.parent)?;
|
if *g == id {
|
||||||
if let Type::Member(mem) = &parent.ty {
|
return Some(&sty.args[i]);
|
||||||
self.follow_ref(mem)
|
|
||||||
} else {
|
|
||||||
Some(mem.parent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn field_type<'a>(&'a self, sty: &'a Type, field: &str) -> Option<&'a Type> {
|
|
||||||
if let Type::Struct(st) = sty {
|
|
||||||
let struc = self.get(st.id)?;
|
|
||||||
let field = struc.fields.get(field)?;
|
|
||||||
if let Type::Generic { id } = field.ty {
|
|
||||||
for (i, g) in struc.generics.iter().enumerate() {
|
|
||||||
if *g == id {
|
|
||||||
return Some(&st.args[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(&field.ty)
|
}
|
||||||
} else if let Type::Module(path) = sty {
|
Some(&field.ty)
|
||||||
let id = self.names.id::<UVar>(path)?;
|
}
|
||||||
|
|
||||||
|
pub fn field_type<'a>(&'a self, ty: &'a Type, field: &str) -> Option<&'a Type> {
|
||||||
|
if let Type::Struct(sty) = ty {
|
||||||
|
self.struct_field_type(sty, field)
|
||||||
|
} else if let Type::Module(path) = ty {
|
||||||
|
let id = self.names.id::<UVar>(path, field)?;
|
||||||
Some(&self.get(id)?.ty)
|
Some(&self.get(id)?.ty)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn follow_ref(&self, m: &FieldRef) -> Option<&Type> {
|
||||||
|
let parent = self.get(m.parent)?;
|
||||||
|
self.field_type(self.follow_type(&parent.ty)?, &m.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_type<'a>(&'a self, v: VarID) -> Option<&'a Type> {
|
||||||
|
self.follow_type(&self.get(v)?.ty)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_type(&mut self, mut var: VarID, set: Type) -> Option<()> {
|
||||||
|
let mut path = Vec::new();
|
||||||
|
while let Type::Field(parent) = &self.get(var)?.ty {
|
||||||
|
var = parent.parent;
|
||||||
|
path.push(parent.name.clone());
|
||||||
|
}
|
||||||
|
let mut ty = &mut self.vars[var.0].as_mut()?.ty;
|
||||||
|
'outer: while let Type::Struct(sty) = ty {
|
||||||
|
let Some(name) = path.pop() else {
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
let struc = &self.structs[sty.id.0].as_ref()?;
|
||||||
|
let field = struc.fields.get(&name)?;
|
||||||
|
let Type::Generic { id } = field.ty else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
for (i, g) in struc.generics.iter().enumerate() {
|
||||||
|
if *g == id {
|
||||||
|
ty = &mut sty.args[i];
|
||||||
|
continue 'outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
*ty = set;
|
||||||
|
Some(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn follow_type<'a>(&'a self, ty: &'a Type) -> Option<&'a Type> {
|
||||||
|
match ty {
|
||||||
|
Type::Field(m) => {
|
||||||
|
let parent = self.get(m.parent)?;
|
||||||
|
self.field_type(self.follow_type(&parent.ty)?, &m.name)
|
||||||
|
}
|
||||||
|
ty => Some(ty),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn type_name(&self, ty: &Type) -> String {
|
pub fn type_name(&self, ty: &Type) -> String {
|
||||||
let mut str = String::new();
|
let mut str = String::new();
|
||||||
match ty {
|
match ty {
|
||||||
@@ -183,29 +230,29 @@ impl UProgram {
|
|||||||
Type::Ref(t) => {
|
Type::Ref(t) => {
|
||||||
str = str + "&" + &self.type_name(t);
|
str = str + "&" + &self.type_name(t);
|
||||||
}
|
}
|
||||||
Type::Error => str += "{error}",
|
|
||||||
Type::Infer => str += "{inferred}",
|
|
||||||
Type::Generic { id } => str += self.names.name(*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 += "()",
|
||||||
Type::Slice(t) => str += &format!("&[{}]", self.type_name(t)),
|
Type::Slice(t) => str += &format!("&[{}]", self.type_name(t)),
|
||||||
|
Type::Error => str += "{error}",
|
||||||
|
Type::Infer => str += "{inferred}",
|
||||||
Type::Placeholder => str += "{placeholder}",
|
Type::Placeholder => str += "{placeholder}",
|
||||||
Type::Module(path) => str += &path.join("::"),
|
Type::Module(path) => str += &path.join("::"),
|
||||||
Type::Member(m) => {
|
Type::Field(m) => {
|
||||||
str += &self
|
str += &self
|
||||||
.ref_ty(m)
|
.follow_ref(m)
|
||||||
.map(|t| self.type_name(t))
|
.map(|t| self.type_name(t))
|
||||||
.unwrap_or("{error}".to_string())
|
.unwrap_or("{error}".to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
str
|
str
|
||||||
}
|
}
|
||||||
pub fn path_var(&self, path: &NamePath) -> Option<VarID> {
|
pub fn path_var(&self, path: &NamePath, name: &str) -> Option<VarID> {
|
||||||
self.names.id(path)
|
self.names.id(path, name)
|
||||||
}
|
}
|
||||||
pub fn path_ty(&self, path: &NamePath) -> Option<&Type> {
|
pub fn path_ty(&self, path: &NamePath, name: &str) -> Option<&Type> {
|
||||||
Some(&self.get(self.path_var(path)?)?.ty)
|
Some(&self.get(self.path_var(path, name)?)?.ty)
|
||||||
}
|
}
|
||||||
fn name_on_stack<K: Kind>(&mut self, id: ID<K>, name: String) {
|
fn name_on_stack<K: Kind>(&mut self, id: ID<K>, name: String) {
|
||||||
let idx = self.name_stack.len() - 1;
|
let idx = self.name_stack.len() - 1;
|
||||||
@@ -230,4 +277,11 @@ impl UProgram {
|
|||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, x)| (ID::new(i), x))
|
.map(|(i, x)| (ID::new(i), x))
|
||||||
}
|
}
|
||||||
|
pub fn cloned_fns(&self) -> impl Iterator<Item = (FnID, UFunc)> + use<'_> {
|
||||||
|
self.fns
|
||||||
|
.iter()
|
||||||
|
.flatten()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, x)| (ID::new(i), x.clone()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::collections::HashMap;
|
|||||||
use super::{assoc::NamePath, GenericID, Len, StructID, UInstruction, UProgram, UVar, VarID};
|
use super::{assoc::NamePath, GenericID, Len, StructID, UInstruction, UProgram, UVar, VarID};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
||||||
pub struct MemberRef {
|
pub struct FieldRef {
|
||||||
pub parent: VarID,
|
pub parent: VarID,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
@@ -18,54 +18,55 @@ pub struct StructTy {
|
|||||||
pub enum Type {
|
pub enum Type {
|
||||||
Bits(u32),
|
Bits(u32),
|
||||||
Struct(StructTy),
|
Struct(StructTy),
|
||||||
|
// is this real? I don't know, it's kind of like infer
|
||||||
Generic { id: GenericID },
|
Generic { id: GenericID },
|
||||||
Fn { args: Vec<Type>, ret: Box<Type> },
|
Fn { args: Vec<Type>, ret: Box<Type> },
|
||||||
Ref(Box<Type>),
|
Ref(Box<Type>),
|
||||||
Slice(Box<Type>),
|
Slice(Box<Type>),
|
||||||
Array(Box<Type>, Len),
|
Array(Box<Type>, Len),
|
||||||
Member(MemberRef),
|
Unit,
|
||||||
|
// fake types
|
||||||
|
Field(FieldRef),
|
||||||
Module(NamePath),
|
Module(NamePath),
|
||||||
Infer,
|
Infer,
|
||||||
Error,
|
Error,
|
||||||
Placeholder,
|
Placeholder,
|
||||||
Unit,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Type {
|
impl Type {
|
||||||
|
pub fn is_resolved(&self) -> bool {
|
||||||
|
!matches!(self, Self::Error | Self::Placeholder | Self::Infer)
|
||||||
|
}
|
||||||
pub fn rf(self) -> Self {
|
pub fn rf(self) -> Self {
|
||||||
Self::Ref(Box::new(self))
|
Type::Ref(Box::new(self))
|
||||||
}
|
}
|
||||||
pub fn arr(self, len: Len) -> Self {
|
pub fn arr(self, len: Len) -> Self {
|
||||||
Self::Array(Box::new(self), len)
|
Type::Array(Box::new(self), len)
|
||||||
}
|
}
|
||||||
pub fn slice(self) -> Self {
|
pub fn slice(self) -> Self {
|
||||||
Self::Slice(Box::new(self))
|
Type::Slice(Box::new(self))
|
||||||
}
|
|
||||||
pub fn is_real(&self) -> bool {
|
|
||||||
!matches!(self, Self::Error | Self::Placeholder | Self::Infer)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UProgram {
|
impl UProgram {
|
||||||
pub fn resolve_types(&mut self) {
|
pub fn resolve_types(&mut self) {
|
||||||
// I LOVE RUST
|
// PARTIAL BORROWING :SOB:
|
||||||
let mut vars = self.vars.clone();
|
let fns: Vec<_> = self.cloned_fns().collect();
|
||||||
// set type of vars referring to functions
|
for (i, f) in &fns {
|
||||||
for (i, f) in self.iter_fns() {
|
let vi = self.fn_var.var(*i);
|
||||||
let vi = self.fn_var.var(i);
|
self.expect_mut(vi).ty = f.ty(self);
|
||||||
vars[vi.0].as_mut().expect("bruh").ty = f.ty(self);
|
|
||||||
}
|
}
|
||||||
for (i, f) in self.iter_fns() {
|
for (i, f) in &fns {
|
||||||
let mut redo_iter = Vec::new();
|
let mut redo_iter = Vec::new();
|
||||||
let mut redo_new = Vec::new();
|
let mut redo_new = Vec::new();
|
||||||
for i in f.flat_iter() {
|
for i in f.flat_iter() {
|
||||||
if self.resolve_instr_types(&mut vars, &i.i).is_none() {
|
if self.resolve_instr_types(&i.i).is_none() {
|
||||||
redo_iter.push(i);
|
redo_iter.push(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while !redo_iter.is_empty() {
|
while !redo_iter.is_empty() {
|
||||||
for &i in &redo_iter {
|
for &i in &redo_iter {
|
||||||
if self.resolve_instr_types(&mut vars, &i.i).is_none() {
|
if self.resolve_instr_types(&i.i).is_none() {
|
||||||
redo_new.push(i);
|
redo_new.push(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,19 +74,19 @@ impl UProgram {
|
|||||||
redo_new.clear();
|
redo_new.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.vars = vars;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_instr_types(&self, vars: &mut [Option<UVar>], i: &UInstruction) -> Option<()> {
|
pub fn resolve_instr_types(&mut self, i: &UInstruction) -> Option<()> {
|
||||||
'outer: {
|
'outer: {
|
||||||
match &i {
|
match &i {
|
||||||
UInstruction::Call { dest, f, args } => {
|
UInstruction::Call { dest, f, args } => {
|
||||||
let fun = self.get_fn_var(f.id).expect("bruh");
|
let fun = self.get_fn_var(f.id).expect("bruh");
|
||||||
vars[dest.id.0].as_mut().expect("bruh").ty = fun.ret.clone();
|
self.expect_mut(dest.id).ty = fun.ret.clone();
|
||||||
for (src, &dest) in args.iter().zip(&fun.args) {
|
for (src, &dest) in args.iter().zip(&fun.args) {
|
||||||
let dest_ty = get(vars, dest)?;
|
let dest_ty = self.get_type(dest)?;
|
||||||
let src_ty = get(vars, src.id)?;
|
let src_ty = self.get_type(src.id)?;
|
||||||
if let Some(ty) = self.match_types(dest_ty, src_ty) {
|
if let Some(ty) = self.match_types(dest_ty, src_ty) {
|
||||||
|
self.expect_mut(dest).ty = ty.clone();
|
||||||
set(vars, dest, ty.clone());
|
set(vars, dest, ty.clone());
|
||||||
set(vars, src.id, ty);
|
set(vars, src.id, ty);
|
||||||
}
|
}
|
||||||
@@ -166,13 +167,16 @@ impl UProgram {
|
|||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn match_types(&self, dest: &Type, src: &Type) -> Option<Type> {
|
pub fn match_types<'a>(&'a self, mut dest: &'a Type, mut src: &'a Type) -> Option<Type> {
|
||||||
|
dest = self.follow_type(dest)?;
|
||||||
|
src = self.follow_type(src)?;
|
||||||
if dest == src {
|
if dest == src {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
match (dest, src) {
|
match (dest, src) {
|
||||||
(Type::Error, _) | (_, Type::Error) => None,
|
(Type::Error, _) | (_, Type::Error) => None,
|
||||||
(Type::Placeholder, _) | (_, Type::Placeholder) => None,
|
(Type::Placeholder, _) | (_, Type::Placeholder) => None,
|
||||||
|
(Type::Infer, Type::Infer) => None,
|
||||||
(Type::Infer, x) | (x, Type::Infer) => Some(x.clone()),
|
(Type::Infer, x) | (x, Type::Infer) => Some(x.clone()),
|
||||||
// TODO: handle constraints?
|
// TODO: handle constraints?
|
||||||
(Type::Generic { id }, x) | (x, Type::Generic { id }) => Some(x.clone()),
|
(Type::Generic { id }, x) | (x, Type::Generic { id }) => Some(x.clone()),
|
||||||
@@ -223,33 +227,3 @@ impl UProgram {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(vars: &[Option<UVar>], id: VarID) -> Option<&Type> {
|
|
||||||
let mut var = vars[id.0]
|
|
||||||
.as_ref()
|
|
||||||
.expect("PARTIAL BORROWING WOULD BE REALLY COOL");
|
|
||||||
if var.ty == Type::Placeholder {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
while let Type::Member(m) = &var.ty {
|
|
||||||
var = vars[m.parent.0].as_ref().expect("xd");
|
|
||||||
}
|
|
||||||
// x.y().z == a.b.c()
|
|
||||||
// 0 ------- member(1, z)
|
|
||||||
// 1 ----- call(2)
|
|
||||||
// 2 --- member(3, y)
|
|
||||||
// 3 - x
|
|
||||||
//
|
|
||||||
// 0 ------- call(1)
|
|
||||||
// 1 ----- member(c, 2)
|
|
||||||
// 2 --- member(b, 3)
|
|
||||||
// 3 - a
|
|
||||||
Some(&var.ty)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set(vars: &mut [Option<UVar>], id: VarID, ty: Type) {
|
|
||||||
vars[id.0]
|
|
||||||
.as_mut()
|
|
||||||
.expect("PARTIAL BORROWING WOULD BE REALLY COOL")
|
|
||||||
.ty = ty;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// TODO: move this into ir, not parser
|
|
||||||
use super::{Type, UInstrInst, UInstruction, UProgram};
|
use super::{Type, UInstrInst, UInstruction, UProgram};
|
||||||
use crate::common::{CompilerMsg, CompilerOutput, FileSpan};
|
use crate::common::{CompilerMsg, CompilerOutput, FileSpan};
|
||||||
|
|
||||||
@@ -33,17 +32,6 @@ impl UProgram {
|
|||||||
spans: vec![self.origins.get(id)],
|
spans: vec![self.origins.get(id)],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if let Some(parent) = &var.parent {
|
|
||||||
let pty = &self.get(parent.var).unwrap().ty;
|
|
||||||
if let Some(ft) = self.field_type(pty, &parent.field) {
|
|
||||||
output.check_assign(self, &var.ty, ft, self.origins.get(id));
|
|
||||||
} else {
|
|
||||||
output.err(CompilerMsg {
|
|
||||||
msg: "invalid parent!".to_string(),
|
|
||||||
spans: vec![self.origins.get(id)],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,6 +96,7 @@ impl UProgram {
|
|||||||
UInstruction::AsmBlock { instructions, args } => {
|
UInstruction::AsmBlock { instructions, args } => {
|
||||||
for arg in args {
|
for arg in args {
|
||||||
// TODO: validate size with enabled targets
|
// TODO: validate size with enabled targets
|
||||||
|
// maybe should happen in lowering? but I think it could happen here
|
||||||
// if let Some(size) = self.size_of_var(arg.var.id)
|
// if let Some(size) = self.size_of_var(arg.var.id)
|
||||||
// && size != 64
|
// && size != 64
|
||||||
// {
|
// {
|
||||||
@@ -125,8 +114,8 @@ impl UProgram {
|
|||||||
}
|
}
|
||||||
UInstruction::Construct { dest, fields } => {
|
UInstruction::Construct { dest, fields } => {
|
||||||
let dest_def = self.expect(dest.id);
|
let dest_def = self.expect(dest.id);
|
||||||
let (tyid, args) = match &dest_def.ty {
|
let sty = match &dest_def.ty {
|
||||||
Type::Struct { id, args } => (*id, args),
|
Type::Struct(sty) => sty,
|
||||||
_ => {
|
_ => {
|
||||||
output.err(CompilerMsg {
|
output.err(CompilerMsg {
|
||||||
msg: format!(
|
msg: format!(
|
||||||
@@ -138,19 +127,19 @@ impl UProgram {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let def = self.expect(tyid);
|
let def = self.expect(sty.id);
|
||||||
for (name, field) in &def.fields {
|
for (name, field) in &def.fields {
|
||||||
if let Some(var) = fields.get(name) {
|
if let Some(var) = fields.get(name) {
|
||||||
let mut sty = &field.ty;
|
let mut fty = &field.ty;
|
||||||
if let Type::Generic { id } = sty {
|
if let Type::Generic { id } = fty {
|
||||||
for (g, a) in def.generics.iter().zip(args) {
|
for (g, a) in def.generics.iter().zip(&sty.args) {
|
||||||
if *g == *id {
|
if *g == *id {
|
||||||
sty = a;
|
fty = a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let ety = &self.expect(var.id).ty;
|
let ety = &self.expect(var.id).ty;
|
||||||
output.check_assign(self, ety, sty, var.span);
|
output.check_assign(self, ety, fty, var.span);
|
||||||
} else {
|
} else {
|
||||||
output.err(CompilerMsg {
|
output.err(CompilerMsg {
|
||||||
msg: format!("field '{}' missing from struct", name),
|
msg: format!("field '{}' missing from struct", name),
|
||||||
|
|||||||
25
src/main.rs
25
src/main.rs
@@ -46,29 +46,30 @@ impl UProgram {
|
|||||||
let mut output = CompilerOutput::new();
|
let mut output = CompilerOutput::new();
|
||||||
|
|
||||||
let mut imports = Imports::new();
|
let mut imports = Imports::new();
|
||||||
imports.insert(Import(
|
imports.insert(Import(vec![path
|
||||||
path.file_name()
|
.file_name()
|
||||||
.expect("bruh")
|
.expect("bruh")
|
||||||
.to_str()
|
.to_str()
|
||||||
.expect("bruh")
|
.expect("bruh")
|
||||||
.to_string(),
|
.to_string()]));
|
||||||
));
|
|
||||||
let mut imported = HashSet::new();
|
let mut imported = HashSet::new();
|
||||||
let mut fid = 0;
|
let mut fid = 0;
|
||||||
|
|
||||||
while !imports.is_empty() {
|
while !imports.is_empty() {
|
||||||
let iter = std::mem::take(&mut imports);
|
let iter = std::mem::take(&mut imports);
|
||||||
for i in iter {
|
for i in iter {
|
||||||
let name = &i.0;
|
let import_path = &i.0;
|
||||||
if imported.contains(&i) {
|
if imported.contains(&i) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let path = parent.join(name).with_extension(FILE_EXT);
|
let mut file_path = parent.to_path_buf();
|
||||||
let text = std::fs::read_to_string(&path).expect("failed to read file");
|
file_path.extend(import_path);
|
||||||
|
file_path.set_extension(FILE_EXT);
|
||||||
|
let text = std::fs::read_to_string(&file_path).expect("failed to read file");
|
||||||
output.file_map.insert(
|
output.file_map.insert(
|
||||||
fid,
|
fid,
|
||||||
SrcFile {
|
SrcFile {
|
||||||
path,
|
path: file_path,
|
||||||
text: text.clone(),
|
text: text.clone(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -77,7 +78,7 @@ impl UProgram {
|
|||||||
let res = PModule::parse(&mut ctx);
|
let res = PModule::parse(&mut ctx);
|
||||||
// println!("Parsed:");
|
// println!("Parsed:");
|
||||||
// println!("{:#?}", res.node);
|
// println!("{:#?}", res.node);
|
||||||
res.lower(name.clone(), &mut program, &mut imports, &mut output);
|
res.lower(import_path.clone(), &mut program, &mut imports, &mut output);
|
||||||
imported.insert(i);
|
imported.insert(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
compiler::arch::riscv::Reg,
|
compiler::arch::riscv::Reg,
|
||||||
ir::{
|
ir::{
|
||||||
arch::riscv64::RV64Instruction, AsmBlockArg, AsmBlockArgType, UInstruction, Type, VarInst,
|
arch::riscv64::RV64Instruction, AsmBlockArg, AsmBlockArgType, Type, UInstruction, VarInst
|
||||||
},
|
},
|
||||||
parser::PAsmBlockArg,
|
parser::PAsmBlockArg,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -27,27 +27,24 @@ impl FnLowerable for PBlock {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ctx.program.push();
|
||||||
// then lower imports
|
// then lower imports
|
||||||
for i_n in &import_nodes {
|
for i_n in &import_nodes {
|
||||||
if let Some(i) = i_n.as_ref() {
|
if let Some(i) = i_n.as_ref() {
|
||||||
let name = &i.0;
|
let name = &i.0;
|
||||||
let import = Import(ctx.program.path_for(name));
|
let path = ctx.program.path_for(name);
|
||||||
ctx
|
let import = Import(path.clone());
|
||||||
.imports
|
if ctx.imports.insert(import) {
|
||||||
.entry(import)
|
ctx.program.def_searchable::<UVar>(
|
||||||
.or_insert(ctx.program.def(name, None, i_n.origin));
|
name,
|
||||||
// I could prevent this if someone imports something twice,
|
Some(UVar {
|
||||||
// but that doesn't seem worth it at all
|
ty: Type::Module(path),
|
||||||
ctx.program.def_searchable::<UVar>(
|
}),
|
||||||
name.clone(),
|
i_n.origin,
|
||||||
Some(UVar {
|
);
|
||||||
ty: Type::Module,
|
}
|
||||||
}),
|
|
||||||
i_n.origin,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.program.push();
|
|
||||||
// then lower const things
|
// then lower const things
|
||||||
let mut structs = Vec::new();
|
let mut structs = Vec::new();
|
||||||
for s in &struct_nodes {
|
for s in &struct_nodes {
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ impl Node<PVarDef> {
|
|||||||
let name = s
|
let name = s
|
||||||
.name
|
.name
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|n| n.to_string())
|
.map_or("{error}", |v| v);
|
||||||
.unwrap_or("{error}".to_string());
|
|
||||||
let ty = match &s.ty {
|
let ty = match &s.ty {
|
||||||
Some(ty) => ty.lower(program, output),
|
Some(ty) => ty.lower(program, output),
|
||||||
None => Type::Infer,
|
None => Type::Infer,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use super::{func::FnLowerCtx, FnLowerable, PExpr, UnaryOp};
|
use super::{func::FnLowerCtx, FnLowerable, PExpr, UnaryOp};
|
||||||
use crate::{
|
use crate::{
|
||||||
ir::{MemberRef, Type, UData, UInstruction, VarInst},
|
ir::{FieldRef, Type, UData, UInstruction, VarInst},
|
||||||
parser::PInfixOp,
|
parser::PInfixOp,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ impl FnLowerable for PExpr {
|
|||||||
super::PLiteral::Number(n) => {
|
super::PLiteral::Number(n) => {
|
||||||
// TODO: temp
|
// TODO: temp
|
||||||
let ty = Type::Bits(64);
|
let ty = Type::Bits(64);
|
||||||
let dest = ctx.program.temp_var(l.origin, Type::Bits(64));
|
let dest = ctx.program.temp_var(l.origin, ty.clone());
|
||||||
let src = ctx.program.def(
|
let src = ctx.program.def(
|
||||||
&format!("num {n:?}"),
|
&format!("num {n:?}"),
|
||||||
Some(UData {
|
Some(UData {
|
||||||
@@ -69,7 +69,7 @@ impl FnLowerable for PExpr {
|
|||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
let fname = ident.as_ref()?.0.clone();
|
let fname = ident.as_ref()?.0.clone();
|
||||||
ctx.temp(Type::Member(MemberRef {
|
ctx.temp(Type::Field(FieldRef {
|
||||||
parent: res1.id,
|
parent: res1.id,
|
||||||
name: fname,
|
name: fname,
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use super::{Imports, CompilerMsg, CompilerOutput, FileSpan, FnLowerable, Node, PFunction};
|
use super::{CompilerMsg, CompilerOutput, FileSpan, FnLowerable, Imports, Node, PFunction};
|
||||||
use crate::{
|
use crate::{
|
||||||
ir::{MemberRef, FnID, Idents, Type, UFunc, UInstrInst, UInstruction, UProgram, UVar, VarInst},
|
ir::{FnID, Idents, Type, UFunc, UInstrInst, UInstruction, UProgram, UVar, VarInst},
|
||||||
parser,
|
parser,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -25,7 +25,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, self.header.origin);
|
let id = p.def_searchable(name, None, self.header.origin);
|
||||||
Some(id)
|
Some(id)
|
||||||
}
|
}
|
||||||
pub fn lower(
|
pub fn lower(
|
||||||
@@ -112,7 +112,7 @@ impl FnLowerCtx<'_> {
|
|||||||
pub fn err_at(&mut self, span: FileSpan, msg: String) {
|
pub fn err_at(&mut self, span: FileSpan, msg: String) {
|
||||||
self.output.err(CompilerMsg::from_span(span, msg))
|
self.output.err(CompilerMsg::from_span(span, msg))
|
||||||
}
|
}
|
||||||
pub fn temp(&mut self, ty: Type) -> VarInst {
|
pub fn temp(&mut self, ty: impl Into<Type>) -> VarInst {
|
||||||
self.program.temp_var(self.origin, ty)
|
self.program.temp_var(self.origin, ty)
|
||||||
}
|
}
|
||||||
pub fn push(&mut self, i: UInstruction) {
|
pub fn push(&mut self, i: UInstruction) {
|
||||||
|
|||||||
@@ -13,12 +13,14 @@ use crate::ir::{Type, UFunc, UProgram};
|
|||||||
impl PModule {
|
impl PModule {
|
||||||
pub fn lower(
|
pub fn lower(
|
||||||
&self,
|
&self,
|
||||||
name: String,
|
path: Vec<String>,
|
||||||
p: &mut UProgram,
|
p: &mut UProgram,
|
||||||
imports: &mut Imports,
|
imports: &mut Imports,
|
||||||
output: &mut CompilerOutput,
|
output: &mut CompilerOutput,
|
||||||
) {
|
) {
|
||||||
let fid = p.def_searchable(name.clone(), None, self.block.origin);
|
let name = path.last().unwrap().clone();
|
||||||
|
p.set_module(path);
|
||||||
|
let fid = p.def_searchable(&name, None, self.block.origin);
|
||||||
p.push_name(&name);
|
p.push_name(&name);
|
||||||
let mut fctx = FnLowerCtx {
|
let mut fctx = FnLowerCtx {
|
||||||
program: p,
|
program: p,
|
||||||
|
|||||||
@@ -46,11 +46,7 @@ impl PStruct {
|
|||||||
span: FileSpan,
|
span: FileSpan,
|
||||||
) -> Option<()> {
|
) -> Option<()> {
|
||||||
p.push();
|
p.push();
|
||||||
let generics = self
|
let generics = self.generics.iter().flat_map(|a| a.lower(p)).collect();
|
||||||
.generics
|
|
||||||
.iter()
|
|
||||||
.flat_map(|a| a.lower(p))
|
|
||||||
.collect();
|
|
||||||
let fields = match &self.fields {
|
let fields = match &self.fields {
|
||||||
PStructFields::Named(nodes) => nodes
|
PStructFields::Named(nodes) => nodes
|
||||||
.iter()
|
.iter()
|
||||||
@@ -84,8 +80,8 @@ 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 s = self.as_ref()?;
|
let s = self.as_ref()?;
|
||||||
let name = s.name.as_ref()?.to_string();
|
let name = s.name.as_ref()?;
|
||||||
let id = p.def_searchable(name.to_string(), None, s.name.origin);
|
let id = p.def_searchable(name, None, s.name.origin);
|
||||||
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) {
|
||||||
|
|||||||
@@ -47,6 +47,6 @@ impl Node<PGenericDef> {
|
|||||||
pub fn lower(&self, p: &mut UProgram) -> Option<GenericID> {
|
pub fn lower(&self, p: &mut UProgram) -> Option<GenericID> {
|
||||||
let s = self.as_ref()?;
|
let s = self.as_ref()?;
|
||||||
let name = s.name.as_ref()?;
|
let name = s.name.as_ref()?;
|
||||||
Some(p.def_searchable(name.to_string(), Some(UGeneric {}), self.origin))
|
Some(p.def_searchable(name, Some(UGeneric {}), self.origin))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user