Compare commits
6 Commits
1acaa29a12
...
b012a46e91
Author | SHA1 | Date | |
---|---|---|---|
b012a46e91 | |||
f139a5ad6c | |||
d9a1e8456d | |||
c83d53ae53 | |||
5fca72a3f9 | |||
0ec427252f |
@ -38,6 +38,7 @@ Currently missing relevant features (TODOs) are:
|
||||
- ~~Extern functions~~ (DONE)
|
||||
- ~~Strings~~ (DONE)
|
||||
- Loops
|
||||
- Debug Information
|
||||
|
||||
### Why "Reid"
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
BINARY="$(echo $1 | cut -d'.' -f1)"".out"
|
||||
|
||||
make clean SRC=$1 && make SRC=$1 && echo ""
|
||||
make clean SRC=$1 ; make SRC=$1 && echo ""
|
||||
|
||||
$BINARY ; echo "Return value: ""$?"
|
||||
|
||||
|
@ -5,12 +5,15 @@ use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use crate::{
|
||||
BlockData, ConstValue, FunctionData, Instr, InstructionData, ModuleData, TerminatorKind, Type,
|
||||
util::match_types,
|
||||
TypeData, util::match_types,
|
||||
};
|
||||
|
||||
#[derive(Clone, Hash, Copy, PartialEq, Eq)]
|
||||
pub struct ModuleValue(pub(crate) usize);
|
||||
|
||||
#[derive(Clone, Hash, Copy, PartialEq, Eq)]
|
||||
pub struct TypeValue(pub(crate) ModuleValue, pub(crate) usize);
|
||||
|
||||
#[derive(Clone, Hash, Copy, PartialEq, Eq)]
|
||||
pub struct FunctionValue(pub(crate) ModuleValue, pub(crate) usize);
|
||||
|
||||
@ -25,6 +28,13 @@ pub struct ModuleHolder {
|
||||
pub(crate) value: ModuleValue,
|
||||
pub(crate) data: ModuleData,
|
||||
pub(crate) functions: Vec<FunctionHolder>,
|
||||
pub(crate) types: Vec<TypeHolder>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TypeHolder {
|
||||
pub(crate) value: TypeValue,
|
||||
pub(crate) data: TypeData,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -65,6 +75,7 @@ impl Builder {
|
||||
value,
|
||||
data,
|
||||
functions: Vec::new(),
|
||||
types: Vec::new(),
|
||||
});
|
||||
value
|
||||
}
|
||||
|
@ -196,6 +196,10 @@ impl ModuleHolder {
|
||||
context.context_ref,
|
||||
);
|
||||
|
||||
for _ty in &self.types {
|
||||
todo!("Do something with types!");
|
||||
}
|
||||
|
||||
// Compile the contents
|
||||
|
||||
let mut functions = HashMap::new();
|
||||
|
@ -263,3 +263,14 @@ pub enum TerminatorKind {
|
||||
Br(BlockValue),
|
||||
CondBr(InstructionValue, BlockValue, BlockValue),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
||||
pub struct TypeData {
|
||||
name: String,
|
||||
kind: CustomTypeKind,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
||||
pub enum CustomTypeKind {
|
||||
Struct(Vec<Type>),
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::{env, fs, path::PathBuf};
|
||||
use std::{env, error::Error, fs, path::PathBuf};
|
||||
|
||||
use reid::compile;
|
||||
use reid_lib::compile::CompileOutput;
|
||||
|
@ -163,6 +163,7 @@ fn main() {
|
||||
name: "test module".to_owned(),
|
||||
imports: vec![],
|
||||
functions: vec![fibonacci, main],
|
||||
typedefs: Vec::new(),
|
||||
path: None,
|
||||
is_main: true,
|
||||
}],
|
||||
|
@ -26,6 +26,7 @@ pub enum TypeKind {
|
||||
U128,
|
||||
String,
|
||||
Array(Box<TypeKind>, u64),
|
||||
Custom(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -43,11 +44,13 @@ pub enum ExpressionKind {
|
||||
VariableName(String),
|
||||
Literal(Literal),
|
||||
Array(Vec<Expression>),
|
||||
Index(Box<Expression>, u64),
|
||||
ArrayIndex(Box<Expression>, u64),
|
||||
StructIndex(Box<Expression>, String),
|
||||
Binop(BinaryOperator, Box<Expression>, Box<Expression>),
|
||||
FunctionCall(Box<FunctionCallExpression>),
|
||||
BlockExpr(Box<Block>),
|
||||
IfExpr(Box<IfExpression>),
|
||||
StructExpression(StructExpression),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
@ -129,6 +132,12 @@ pub enum ReturnType {
|
||||
Hard,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct StructExpression {
|
||||
name: String,
|
||||
fields: Vec<(String, Expression)>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Block(
|
||||
pub Vec<BlockLevelStatement>,
|
||||
@ -142,7 +151,8 @@ pub struct VariableReference(pub VariableReferenceKind, pub TokenRange);
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum VariableReferenceKind {
|
||||
Name(String, TokenRange),
|
||||
Index(Box<VariableReference>, u64),
|
||||
ArrayIndex(Box<VariableReference>, u64),
|
||||
StructIndex(Box<VariableReference>, String),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -157,11 +167,31 @@ pub enum BlockLevelStatement {
|
||||
Return(ReturnType, Expression),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TypeDefinition {
|
||||
name: String,
|
||||
kind: TypeDefinitionKind,
|
||||
range: TokenRange,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum TypeDefinitionKind {
|
||||
Struct(Vec<StructDefinitionField>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StructDefinitionField {
|
||||
name: String,
|
||||
ty: Type,
|
||||
range: TokenRange,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum TopLevelStatement {
|
||||
Import(ImportStatement),
|
||||
ExternFunction(FunctionSignature),
|
||||
FunctionDefinition(FunctionDefinition),
|
||||
TypeDefinition(TypeDefinition),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -76,10 +76,24 @@ impl Parse for PrimaryExpression {
|
||||
)
|
||||
} else if let Ok(ifexpr) = stream.parse() {
|
||||
Expression(Kind::IfExpr(Box::new(ifexpr)), stream.get_range().unwrap())
|
||||
} else if let (Some(Token::Identifier(_)), Some(Token::BraceOpen)) =
|
||||
(stream.peek(), stream.peek2())
|
||||
{
|
||||
Expression(
|
||||
Kind::StructExpression(stream.parse()?),
|
||||
stream.get_range().unwrap(),
|
||||
)
|
||||
} else if let Some(token) = stream.next() {
|
||||
match &token {
|
||||
Token::Identifier(v) => {
|
||||
Expression(Kind::VariableName(v.clone()), stream.get_range().unwrap())
|
||||
if let Some(Token::BraceOpen) = stream.peek() {
|
||||
Expression(
|
||||
Kind::StructExpression(stream.parse()?),
|
||||
stream.get_range().unwrap(),
|
||||
)
|
||||
} else {
|
||||
Expression(Kind::VariableName(v.clone()), stream.get_range().unwrap())
|
||||
}
|
||||
}
|
||||
Token::DecimalValue(v) => Expression(
|
||||
Kind::Literal(Literal::Number(*v)),
|
||||
@ -120,11 +134,21 @@ impl Parse for PrimaryExpression {
|
||||
Err(stream.expected_err("expression")?)?
|
||||
};
|
||||
|
||||
while let Ok(ValueIndex(idx)) = stream.parse() {
|
||||
expr = Expression(
|
||||
ExpressionKind::Index(Box::new(expr), idx),
|
||||
stream.get_range().unwrap(),
|
||||
);
|
||||
while let Ok(index) = stream.parse::<ValueIndex>() {
|
||||
match index {
|
||||
ValueIndex::Array(ArrayValueIndex(idx)) => {
|
||||
expr = Expression(
|
||||
ExpressionKind::ArrayIndex(Box::new(expr), idx),
|
||||
stream.get_range().unwrap(),
|
||||
);
|
||||
}
|
||||
ValueIndex::Struct(StructValueIndex(name)) => {
|
||||
expr = Expression(
|
||||
ExpressionKind::StructIndex(Box::new(expr), name),
|
||||
stream.get_range().unwrap(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(PrimaryExpression(expr))
|
||||
@ -401,9 +425,9 @@ impl Parse for VariableReference {
|
||||
stream.get_range().unwrap(),
|
||||
);
|
||||
|
||||
while let Ok(ValueIndex(idx)) = stream.parse() {
|
||||
while let Ok(ArrayValueIndex(idx)) = stream.parse() {
|
||||
var_ref = VariableReference(
|
||||
VariableReferenceKind::Index(Box::new(var_ref), idx),
|
||||
VariableReferenceKind::ArrayIndex(Box::new(var_ref), idx),
|
||||
stream.get_range().unwrap(),
|
||||
);
|
||||
}
|
||||
@ -415,21 +439,101 @@ impl Parse for VariableReference {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct ValueIndex(u64);
|
||||
impl Parse for StructExpression {
|
||||
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
||||
let Some(Token::Identifier(name)) = stream.next() else {
|
||||
return Err(stream.expected_err("struct identifier")?);
|
||||
};
|
||||
stream.expect(Token::BraceOpen)?;
|
||||
let named_list = stream.parse::<NamedFieldList<Expression>>()?;
|
||||
let fields = named_list.0.into_iter().map(|f| (f.0, f.1)).collect();
|
||||
|
||||
stream.expect(Token::BraceClose)?;
|
||||
|
||||
Ok(StructExpression { name, fields })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NamedFieldList<T: Parse + std::fmt::Debug>(Vec<NamedField<T>>);
|
||||
|
||||
impl<T: Parse + std::fmt::Debug> Parse for NamedFieldList<T> {
|
||||
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
||||
let mut fields = Vec::new();
|
||||
while let Ok(field) = stream.parse() {
|
||||
fields.push(field);
|
||||
match stream.peek() {
|
||||
Some(Token::Comma) => {
|
||||
stream.next();
|
||||
} // Consume comma
|
||||
Some(Token::BraceClose) => break,
|
||||
Some(_) | None => Err(stream.expected_err("another field or closing brace")?)?,
|
||||
}
|
||||
}
|
||||
Ok(NamedFieldList(fields))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NamedField<T: Parse + std::fmt::Debug>(String, T, TokenRange);
|
||||
|
||||
impl<T: Parse + std::fmt::Debug> Parse for NamedField<T> {
|
||||
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
||||
let Some(Token::Identifier(field_name)) = stream.next() else {
|
||||
return Err(stream.expected_err("type name")?);
|
||||
};
|
||||
stream.expect(Token::Colon)?;
|
||||
let value = stream.parse()?;
|
||||
|
||||
Ok(NamedField(field_name, value, stream.get_range().unwrap()))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ValueIndex {
|
||||
Array(ArrayValueIndex),
|
||||
Struct(StructValueIndex),
|
||||
}
|
||||
|
||||
impl Parse for ValueIndex {
|
||||
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
||||
match stream.peek() {
|
||||
Some(Token::BracketOpen) => Ok(ValueIndex::Array(stream.parse()?)),
|
||||
Some(Token::Dot) => Ok(ValueIndex::Struct(stream.parse()?)),
|
||||
_ => Err(stream.expected_err("value or struct index")?),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct ArrayValueIndex(u64);
|
||||
|
||||
impl Parse for ArrayValueIndex {
|
||||
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
||||
stream.expect(Token::BracketOpen)?;
|
||||
if let Some(Token::DecimalValue(idx)) = stream.next() {
|
||||
stream.expect(Token::BracketClose)?;
|
||||
Ok(ValueIndex(idx))
|
||||
Ok(ArrayValueIndex(idx))
|
||||
} else {
|
||||
return Err(stream.expected_err("array index (number)")?);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct StructValueIndex(String);
|
||||
|
||||
impl Parse for StructValueIndex {
|
||||
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
||||
stream.expect(Token::Dot)?;
|
||||
if let Some(Token::Identifier(name)) = stream.next() {
|
||||
Ok(StructValueIndex(name))
|
||||
} else {
|
||||
return Err(stream.expected_err("struct index (number)")?);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for BlockLevelStatement {
|
||||
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
||||
use BlockLevelStatement as Stmt;
|
||||
@ -476,6 +580,33 @@ impl Parse for SetStatement {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StructDefinition(String, Vec<StructDefinitionField>, TokenRange);
|
||||
|
||||
impl Parse for StructDefinition {
|
||||
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
||||
stream.expect(Token::Struct)?;
|
||||
|
||||
let Some(Token::Identifier(name)) = stream.next() else {
|
||||
return Err(stream.expected_err("identifier")?);
|
||||
};
|
||||
|
||||
stream.expect(Token::BraceOpen)?;
|
||||
let named_fields = stream.parse::<NamedFieldList<Type>>()?;
|
||||
let fields = named_fields
|
||||
.0
|
||||
.into_iter()
|
||||
.map(|f| StructDefinitionField {
|
||||
name: f.0,
|
||||
ty: f.1,
|
||||
range: f.2,
|
||||
})
|
||||
.collect();
|
||||
stream.expect(Token::BraceClose)?;
|
||||
Ok(StructDefinition(name, fields, stream.get_range().unwrap()))
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for TopLevelStatement {
|
||||
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
||||
use TopLevelStatement as Stmt;
|
||||
@ -491,6 +622,14 @@ impl Parse for TopLevelStatement {
|
||||
Some(Token::FnKeyword) | Some(Token::PubKeyword) => {
|
||||
Stmt::FunctionDefinition(stream.parse()?)
|
||||
}
|
||||
Some(Token::Struct) => {
|
||||
let StructDefinition(name, fields, range) = stream.parse::<StructDefinition>()?;
|
||||
Stmt::TypeDefinition(TypeDefinition {
|
||||
name,
|
||||
kind: TypeDefinitionKind::Struct(fields),
|
||||
range,
|
||||
})
|
||||
}
|
||||
_ => Err(stream.expected_err("import or fn")?)?,
|
||||
})
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ impl ast::Module {
|
||||
pub fn process(&self) -> mir::Module {
|
||||
let mut imports = Vec::new();
|
||||
let mut functions = Vec::new();
|
||||
let mut typedefs = Vec::new();
|
||||
|
||||
use ast::TopLevelStatement::*;
|
||||
for stmt in &self.top_level_statements {
|
||||
@ -62,6 +63,23 @@ impl ast::Module {
|
||||
};
|
||||
functions.push(def);
|
||||
}
|
||||
TypeDefinition(ast::TypeDefinition { name, kind, range }) => {
|
||||
let def = mir::TypeDefinition {
|
||||
name: name.clone(),
|
||||
kind: match kind {
|
||||
ast::TypeDefinitionKind::Struct(struct_definition_fields) => {
|
||||
mir::TypeDefinitionKind::Struct(
|
||||
struct_definition_fields
|
||||
.iter()
|
||||
.map(|s| (s.name.clone(), s.ty.clone().into()))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
},
|
||||
meta: (*range).into(),
|
||||
};
|
||||
typedefs.push(def);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,6 +89,7 @@ impl ast::Module {
|
||||
functions,
|
||||
path: self.path.clone(),
|
||||
is_main: self.is_main,
|
||||
typedefs,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -151,8 +170,14 @@ impl ast::VariableReferenceKind {
|
||||
(*range).into(),
|
||||
))
|
||||
}
|
||||
ast::VariableReferenceKind::Index(var_ref, idx) => {
|
||||
mir::IndexedVariableReferenceKind::Index(Box::new(var_ref.process()), *idx)
|
||||
ast::VariableReferenceKind::ArrayIndex(var_ref, idx) => {
|
||||
mir::IndexedVariableReferenceKind::ArrayIndex(Box::new(var_ref.process()), *idx)
|
||||
}
|
||||
ast::VariableReferenceKind::StructIndex(var_ref, name) => {
|
||||
mir::IndexedVariableReferenceKind::StructIndex(
|
||||
Box::new(var_ref.process()),
|
||||
name.clone(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -193,11 +218,24 @@ impl ast::Expression {
|
||||
ast::ExpressionKind::Array(expressions) => {
|
||||
mir::ExprKind::Array(expressions.iter().map(|e| e.process()).collect())
|
||||
}
|
||||
ast::ExpressionKind::Index(expression, idx) => mir::ExprKind::Index(
|
||||
ast::ExpressionKind::ArrayIndex(expression, idx) => mir::ExprKind::ArrayIndex(
|
||||
Box::new(expression.process()),
|
||||
mir::TypeKind::Vague(mir::VagueType::Unknown),
|
||||
*idx,
|
||||
),
|
||||
ast::ExpressionKind::StructExpression(struct_init) => mir::ExprKind::Struct(
|
||||
struct_init.name.clone(),
|
||||
struct_init
|
||||
.fields
|
||||
.iter()
|
||||
.map(|(n, e)| (n.clone(), e.process()))
|
||||
.collect(),
|
||||
),
|
||||
ast::ExpressionKind::StructIndex(expression, name) => mir::ExprKind::StructIndex(
|
||||
Box::new(expression.process()),
|
||||
mir::TypeKind::Vague(mir::VagueType::Unknown),
|
||||
name.clone(),
|
||||
),
|
||||
};
|
||||
|
||||
mir::Expression(kind, self.1.into())
|
||||
@ -249,6 +287,7 @@ impl From<ast::TypeKind> for mir::TypeKind {
|
||||
mir::TypeKind::Array(Box::new(mir::TypeKind::from(*type_kind.clone())), *length)
|
||||
}
|
||||
ast::TypeKind::String => mir::TypeKind::StringPtr,
|
||||
ast::TypeKind::Custom(_) => todo!("Add processing for custom types"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ impl IndexedVariableReference {
|
||||
.get(name)
|
||||
.cloned()
|
||||
.map(|v| (v, Vec::new())),
|
||||
mir::IndexedVariableReferenceKind::Index(inner, idx) => {
|
||||
mir::IndexedVariableReferenceKind::ArrayIndex(inner, idx) => {
|
||||
let (inner_val, mut indices) = inner.get_stack_value(scope)?;
|
||||
|
||||
match &inner_val.1 {
|
||||
@ -184,6 +184,9 @@ impl IndexedVariableReference {
|
||||
_ => panic!("Tried to codegen indexing a non-indexable value!"),
|
||||
}
|
||||
}
|
||||
mir::IndexedVariableReferenceKind::StructIndex(indexed_variable_reference, _) => {
|
||||
todo!("codegen for indexed var refrence")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -385,7 +388,7 @@ impl mir::Expression {
|
||||
None
|
||||
}
|
||||
}
|
||||
mir::ExprKind::Index(expression, val_t, idx) => {
|
||||
mir::ExprKind::ArrayIndex(expression, val_t, idx) => {
|
||||
let array = expression.codegen(scope)?;
|
||||
let ptr = scope
|
||||
.block
|
||||
@ -428,6 +431,10 @@ impl mir::Expression {
|
||||
|
||||
Some(array)
|
||||
}
|
||||
mir::ExprKind::StructIndex(expression, type_kind, _) => {
|
||||
todo!("codegen for struct index")
|
||||
}
|
||||
mir::ExprKind::Struct(_, items) => todo!("codegen for struct expression"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -511,6 +518,7 @@ impl TypeKind {
|
||||
TypeKind::Array(elem_t, _) => Type::Ptr(Box::new(elem_t.get_type())),
|
||||
TypeKind::Void => Type::Void,
|
||||
TypeKind::Vague(_) => panic!("Tried to compile a vague type!"),
|
||||
TypeKind::CustomType(_, custom_type_kind) => todo!("codegen for custom type"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,8 @@ pub enum Token {
|
||||
False,
|
||||
/// `extern`
|
||||
Extern,
|
||||
/// `struct`
|
||||
Struct,
|
||||
|
||||
// Symbols
|
||||
/// `;`
|
||||
@ -74,6 +76,8 @@ pub enum Token {
|
||||
BracketClose,
|
||||
/// `,`
|
||||
Comma,
|
||||
/// `.`
|
||||
Dot,
|
||||
|
||||
Eof,
|
||||
}
|
||||
@ -211,6 +215,7 @@ pub fn tokenize<T: Into<String>>(to_tokenize: T) -> Result<Vec<FullToken>, Error
|
||||
"false" => Token::False,
|
||||
"extern" => Token::Extern,
|
||||
"pub" => Token::PubKeyword,
|
||||
"struct" => Token::Struct,
|
||||
_ => Token::Identifier(value),
|
||||
};
|
||||
variant
|
||||
@ -249,6 +254,7 @@ pub fn tokenize<T: Into<String>>(to_tokenize: T) -> Result<Vec<FullToken>, Error
|
||||
'{' => Token::BraceOpen,
|
||||
'}' => Token::BraceClose,
|
||||
',' => Token::Comma,
|
||||
'.' => Token::Dot,
|
||||
// Invalid token
|
||||
_ => Err(Error::InvalidToken(*character, cursor.position))?,
|
||||
};
|
||||
|
@ -23,6 +23,9 @@ impl Display for Module {
|
||||
for import in &self.imports {
|
||||
writeln!(inner_f, "{}", import)?;
|
||||
}
|
||||
for typedef in &self.typedefs {
|
||||
writeln!(inner_f, "{}", typedef)?;
|
||||
}
|
||||
for fun in &self.functions {
|
||||
writeln!(inner_f, "{}", fun)?;
|
||||
}
|
||||
@ -36,6 +39,31 @@ impl Display for Import {
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for TypeDefinition {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "type {} = ", self.name)?;
|
||||
Display::fmt(&self.kind, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for TypeDefinitionKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
TypeDefinitionKind::Struct(items) => {
|
||||
write!(f, "struct ")?;
|
||||
f.write_char('{')?;
|
||||
writeln!(f)?;
|
||||
let mut state = Default::default();
|
||||
let mut inner_f = PadAdapter::wrap(f, &mut state);
|
||||
for (field_name, field_ty) in items {
|
||||
writeln!(inner_f, "{}: {:?},", field_name, field_ty)?;
|
||||
}
|
||||
f.write_char('}')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for FunctionDefinition {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
@ -130,7 +158,7 @@ impl Display for ExprKind {
|
||||
ExprKind::FunctionCall(fc) => Display::fmt(fc, f),
|
||||
ExprKind::If(if_exp) => Display::fmt(&if_exp, f),
|
||||
ExprKind::Block(block) => Display::fmt(block, f),
|
||||
ExprKind::Index(expression, elem_ty, idx) => {
|
||||
ExprKind::ArrayIndex(expression, elem_ty, idx) => {
|
||||
Display::fmt(&expression, f)?;
|
||||
write!(f, "<{}>", elem_ty)?;
|
||||
write_index(f, *idx)
|
||||
@ -152,6 +180,28 @@ impl Display for ExprKind {
|
||||
}
|
||||
f.write_char(']')
|
||||
}
|
||||
ExprKind::Struct(name, items) => {
|
||||
write!(f, "{} ", name)?;
|
||||
|
||||
f.write_char('{')?;
|
||||
let mut state = Default::default();
|
||||
let mut inner_f = PadAdapter::wrap(f, &mut state);
|
||||
let mut iter = items.iter();
|
||||
if let Some((name, expr)) = iter.next() {
|
||||
write!(inner_f, "\n{}: {}", name, expr)?;
|
||||
while let Some((name, expr)) = iter.next() {
|
||||
writeln!(inner_f, ",")?;
|
||||
write!(inner_f, "{}: {}", name, expr)?;
|
||||
}
|
||||
writeln!(inner_f, "")?;
|
||||
}
|
||||
f.write_char('}')
|
||||
}
|
||||
ExprKind::StructIndex(expression, type_kind, name) => {
|
||||
Display::fmt(&expression, f)?;
|
||||
write!(f, "<{}>", type_kind)?;
|
||||
write_access(f, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -190,10 +240,14 @@ impl Display for IndexedVariableReference {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match &self.kind {
|
||||
IndexedVariableReferenceKind::Named(name) => Display::fmt(name, f),
|
||||
IndexedVariableReferenceKind::Index(variable_reference_kind, idx) => {
|
||||
Display::fmt(&variable_reference_kind, f)?;
|
||||
IndexedVariableReferenceKind::ArrayIndex(var_ref, idx) => {
|
||||
Display::fmt(&var_ref, f)?;
|
||||
write_index(f, *idx)
|
||||
}
|
||||
IndexedVariableReferenceKind::StructIndex(var_ref, name) => {
|
||||
Display::fmt(&var_ref, f)?;
|
||||
write_access(f, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -254,3 +308,8 @@ fn write_index(f: &mut std::fmt::Formatter<'_>, idx: u64) -> std::fmt::Result {
|
||||
Display::fmt(&idx, f)?;
|
||||
f.write_char(']')
|
||||
}
|
||||
|
||||
fn write_access(f: &mut std::fmt::Formatter<'_>, name: &String) -> std::fmt::Result {
|
||||
f.write_char('.')?;
|
||||
Display::fmt(name, f)
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::token_stream::TokenRange;
|
||||
use crate::{ast::Type, token_stream::TokenRange};
|
||||
|
||||
mod display;
|
||||
pub mod linker;
|
||||
@ -65,6 +65,8 @@ pub enum TypeKind {
|
||||
StringPtr,
|
||||
#[error("[{0}; {1}]")]
|
||||
Array(Box<TypeKind>, u64),
|
||||
#[error("{0} ({1})")]
|
||||
CustomType(String, CustomTypeKind),
|
||||
#[error(transparent)]
|
||||
Vague(#[from] VagueType),
|
||||
}
|
||||
@ -79,6 +81,14 @@ pub enum VagueType {
|
||||
TypeRef(usize),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
|
||||
pub enum CustomTypeKind {
|
||||
#[error("struct({0:?})")]
|
||||
Struct(Vec<TypeKind>),
|
||||
#[error("CustomType")]
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl TypeKind {
|
||||
pub fn known(&self) -> Result<TypeKind, VagueType> {
|
||||
if let TypeKind::Vague(vague) = self {
|
||||
@ -107,6 +117,7 @@ impl TypeKind {
|
||||
TypeKind::U128 => false,
|
||||
TypeKind::StringPtr => false,
|
||||
TypeKind::Array(_, _) => false,
|
||||
TypeKind::CustomType(_, _) => false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,8 +137,9 @@ impl TypeKind {
|
||||
Bool => true,
|
||||
Vague(_) => false,
|
||||
Void => false,
|
||||
TypeKind::StringPtr => false,
|
||||
StringPtr => false,
|
||||
Array(_, _) => false,
|
||||
TypeKind::CustomType(_, _) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -217,8 +229,10 @@ pub struct Import(pub Vec<String>, pub Metadata);
|
||||
#[derive(Debug)]
|
||||
pub enum ExprKind {
|
||||
Variable(NamedVariableRef),
|
||||
Index(Box<Expression>, TypeKind, u64),
|
||||
ArrayIndex(Box<Expression>, TypeKind, u64),
|
||||
StructIndex(Box<Expression>, TypeKind, String),
|
||||
Array(Vec<Expression>),
|
||||
Struct(String, Vec<(String, Expression)>),
|
||||
Literal(Literal),
|
||||
BinOp(BinaryOperator, Box<Expression>, Box<Expression>),
|
||||
FunctionCall(FunctionCall),
|
||||
@ -294,7 +308,8 @@ pub struct IndexedVariableReference {
|
||||
#[derive(Debug)]
|
||||
pub enum IndexedVariableReferenceKind {
|
||||
Named(NamedVariableRef),
|
||||
Index(Box<IndexedVariableReference>, u64),
|
||||
ArrayIndex(Box<IndexedVariableReference>, u64),
|
||||
StructIndex(Box<IndexedVariableReference>, String),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -306,11 +321,24 @@ pub enum StmtKind {
|
||||
Expression(Expression),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TypeDefinition {
|
||||
pub name: String,
|
||||
pub kind: TypeDefinitionKind,
|
||||
pub meta: Metadata,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum TypeDefinitionKind {
|
||||
Struct(Vec<(String, Type)>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Module {
|
||||
pub name: String,
|
||||
pub imports: Vec<Import>,
|
||||
pub functions: Vec<FunctionDefinition>,
|
||||
pub typedefs: Vec<TypeDefinition>,
|
||||
pub path: Option<PathBuf>,
|
||||
pub is_main: bool,
|
||||
}
|
||||
|
@ -427,7 +427,7 @@ impl Expression {
|
||||
Ok((_, ty)) => Ok(ty),
|
||||
Err(e) => Err(e),
|
||||
},
|
||||
ExprKind::Index(expression, elem_ty, idx) => {
|
||||
ExprKind::ArrayIndex(expression, elem_ty, idx) => {
|
||||
// Try to unwrap hint type from array if possible
|
||||
let hint_t = hint_t.map(|t| match t {
|
||||
TypeKind::Array(type_kind, _) => &type_kind,
|
||||
@ -487,6 +487,10 @@ impl Expression {
|
||||
}
|
||||
}
|
||||
}
|
||||
ExprKind::StructIndex(expression, type_kind, _) => {
|
||||
todo!("typechecking for struct index")
|
||||
}
|
||||
ExprKind::Struct(_, items) => todo!("typechecking for struct expression"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -500,7 +504,7 @@ impl IndexedVariableReference {
|
||||
IndexedVariableReferenceKind::Named(NamedVariableRef(_, name, _)) => {
|
||||
Ok(storage.get(&name).cloned())
|
||||
}
|
||||
IndexedVariableReferenceKind::Index(inner_ref, _) => {
|
||||
IndexedVariableReferenceKind::ArrayIndex(inner_ref, _) => {
|
||||
if let Some(var) = inner_ref.get_variable(storage)? {
|
||||
match &var.ty {
|
||||
TypeKind::Array(inner_ty, _) => Ok(Some(ScopeVariable {
|
||||
@ -513,6 +517,9 @@ impl IndexedVariableReference {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
IndexedVariableReferenceKind::StructIndex(indexed_variable_reference, _) => {
|
||||
todo!("struct index refrence typecheck")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ impl IndexedVariableReference {
|
||||
super::IndexedVariableReferenceKind::Named(NamedVariableRef(_, name, _)) => {
|
||||
Ok(hints.find_hint(&name))
|
||||
}
|
||||
super::IndexedVariableReferenceKind::Index(inner, _) => {
|
||||
super::IndexedVariableReferenceKind::ArrayIndex(inner, _) => {
|
||||
if let Some((mutable, inner_ref)) = inner.find_hint(hints)? {
|
||||
// Check that the resolved type is at least an array, no
|
||||
// need for further resolution.
|
||||
@ -177,6 +177,9 @@ impl IndexedVariableReference {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
super::IndexedVariableReferenceKind::StructIndex(indexed_variable_reference, _) => {
|
||||
todo!("struct index refrence type inference")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -283,7 +286,7 @@ impl Expression {
|
||||
ReturnKind::Soft => Ok(block_ref.1),
|
||||
}
|
||||
}
|
||||
ExprKind::Index(expression, index_ty, _) => {
|
||||
ExprKind::ArrayIndex(expression, index_ty, _) => {
|
||||
let expr_ty = expression.infer_types(state, type_refs)?;
|
||||
|
||||
// Check that the resolved type is at least an array, no
|
||||
@ -336,6 +339,10 @@ impl Expression {
|
||||
}
|
||||
}
|
||||
}
|
||||
ExprKind::StructIndex(expression, type_kind, _) => {
|
||||
todo!("type inference for struct indexes")
|
||||
}
|
||||
ExprKind::Struct(_, items) => todo!("type inference for struct expression"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
use crate::util::try_all;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -87,7 +89,7 @@ impl ReturnType for Expression {
|
||||
Block(block) => block.return_type(),
|
||||
FunctionCall(fcall) => fcall.return_type(),
|
||||
If(expr) => expr.return_type(),
|
||||
Index(expression, _, _) => {
|
||||
ArrayIndex(expression, _, _) => {
|
||||
let expr_type = expression.return_type()?;
|
||||
if let (_, TypeKind::Array(elem_ty, _)) = expr_type {
|
||||
Ok((ReturnKind::Soft, *elem_ty))
|
||||
@ -106,6 +108,18 @@ impl ReturnType for Expression {
|
||||
TypeKind::Array(Box::new(first.1), expressions.len() as u64),
|
||||
))
|
||||
}
|
||||
StructIndex(expression, type_kind, _) => todo!("todo return type for struct index"),
|
||||
Struct(name, items) => {
|
||||
let f_types = try_all(items.iter().map(|e| e.1.return_type()).collect())
|
||||
.map_err(|e| unsafe { e.get_unchecked(0).clone() })?
|
||||
.iter()
|
||||
.map(|r| r.1.clone())
|
||||
.collect();
|
||||
Ok((
|
||||
ReturnKind::Soft,
|
||||
TypeKind::CustomType(name.clone(), CustomTypeKind::Struct(f_types)),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -165,9 +179,12 @@ impl IndexedVariableReference {
|
||||
pub fn get_name(&self) -> String {
|
||||
match &self.kind {
|
||||
IndexedVariableReferenceKind::Named(NamedVariableRef(_, name, _)) => name.clone(),
|
||||
IndexedVariableReferenceKind::Index(inner, idx) => {
|
||||
IndexedVariableReferenceKind::ArrayIndex(inner, idx) => {
|
||||
format!("{}[{}]", inner.get_name(), idx)
|
||||
}
|
||||
IndexedVariableReferenceKind::StructIndex(inner, name) => {
|
||||
format!("{}.{}", inner.get_name(), name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,7 +193,8 @@ impl IndexedVariableReference {
|
||||
IndexedVariableReferenceKind::Named(NamedVariableRef(ty, _, _)) => {
|
||||
*ty = new_ty.clone();
|
||||
}
|
||||
IndexedVariableReferenceKind::Index(inner, _) => inner.update_type(new_ty),
|
||||
IndexedVariableReferenceKind::ArrayIndex(inner, _) => inner.update_type(new_ty),
|
||||
IndexedVariableReferenceKind::StructIndex(inner, _) => inner.update_type(new_ty),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -63,6 +63,14 @@ impl<'a, 'b> TokenStream<'a, 'b> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn peek2(&mut self) -> Option<Token> {
|
||||
if self.tokens.len() < (self.position + 1) {
|
||||
None
|
||||
} else {
|
||||
Some(self.tokens[self.position + 1].token.clone())
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse the next value of trait Parse. If the parse succeeded, the related
|
||||
/// tokens are consumed, otherwise token stream does not advance.
|
||||
///
|
||||
|
15
reid_src/struct.reid
Normal file
15
reid_src/struct.reid
Normal file
@ -0,0 +1,15 @@
|
||||
// Arithmetic, function calls and imports!
|
||||
|
||||
struct Test {
|
||||
field: i32,
|
||||
second: u32
|
||||
}
|
||||
|
||||
fn main() -> u32 {
|
||||
let value = Test {
|
||||
field: 5,
|
||||
second: 3,
|
||||
};
|
||||
|
||||
return Test.second;
|
||||
}
|
Loading…
Reference in New Issue
Block a user