Skip to content

Commit

Permalink
Add structs
Browse files Browse the repository at this point in the history
  • Loading branch information
didrikmunther committed Apr 24, 2024
1 parent ffe20e0 commit 2ea2262
Show file tree
Hide file tree
Showing 20 changed files with 239 additions and 74 deletions.
18 changes: 17 additions & 1 deletion bootstrap.rost
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
// This program is supposed to be the initial bootstrapping of the language.

fn main(argc: int, argv: &&char) {
struct Vec<T> {

}

fn main(argc: int, argv: &&char) {
if(argc < 2) {
printf("Insufficient arguments, usage: %s <program input>\n", argv[0]);
}

let input = argv[1];
let tokens: Vec<int> = Vec::new();
tokens.push(5);

// let i = 0;

// while(input[i]) {

// }
}
3 changes: 2 additions & 1 deletion src/compiler/assignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ impl Program {
let typ = declaration
.typ
.as_ref()
.map(|typ| self.get_variable_type(typ));
.map(|typ| self.get_variable_type(typ))
.transpose()?;

if let Some(typ) = typ {
if typ != infered {
Expand Down
1 change: 1 addition & 0 deletions src/compiler/definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ pub struct Struct {
pub struct SystemCall {
pub identifier: String,
pub nargs: usize,
pub returns: bool
}

#[derive(Debug)]
Expand Down
7 changes: 7 additions & 0 deletions src/compiler/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use super::scope::variable::VariableType;
pub enum CompilerErrorKind {
UndefinedVariable(String),
UndefinedFunction(String),
UnknownType(String),
RedeclaredVariable(String, Range<usize>),
DereferenceNonPointer(VariableType),
MissingMainFunction,
Expand Down Expand Up @@ -111,6 +112,12 @@ impl CompilerError {
self.pos.clone(),
)]
}
CompilerErrorKind::UnknownType(identifier) => {
vec![(
format!("Unknown type: {identifier}"),
self.pos.clone(),
)]
}
CompilerErrorKind::WrongBinaryExpressionTypes {
got,
expected,
Expand Down
44 changes: 32 additions & 12 deletions src/compiler/function_call.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
use crate::parser::definition::{Expression, FunctionCall};
use crate::{
lexer::Keyword,
parser::{
definition::{Expression, FunctionCall},
types::{Type, TypeIdentifier},
},
};

use super::{
builder::Builder,
Expand All @@ -8,9 +14,24 @@ use super::{
scope::variable::VariableType,
};

static BUILT_IN: &[&str] = &["printf"];

impl Program {
fn handle_system_call(
&mut self,
system_call: &SystemCallDefinition,
expression: &Expression,
fcall: &FunctionCall,
identifier: String,
) -> Result<Builder, CompilerError> {
Ok(Builder::new().push(Procedure::new(
expression.pos.clone(),
ProcedureKind::SystemCall(SystemCall {
nargs: fcall.args.len(),
identifier,
returns: system_call.returns.is_some(),
}),
)))
}

pub fn handle_function_call(
&mut self,
expression: &Expression,
Expand All @@ -24,14 +45,13 @@ impl Program {
}

let identifier = fcall.left.get_string().unwrap().to_string();
if BUILT_IN.contains(&identifier.as_str()) {
return Ok(builder.push(Procedure::new(
expression.pos.clone(),
ProcedureKind::SystemCall(SystemCall {
nargs: fcall.args.len(),
identifier,
}),
)));
if let Some(system_call) = SYSTEM_CALL.get(&identifier) {
return Ok(builder.append(self.handle_system_call(
system_call,
expression,
fcall,
identifier,
)?));
}

let Some(variable) = self.get_variable(&identifier) else {
Expand All @@ -57,7 +77,7 @@ impl Program {

for (par, arg) in function.parameters.iter().zip(&fcall.args) {
let arg_type = self.infer_type(arg)?;
let par_type = self.get_variable_type(&par.typ);
let par_type = self.get_variable_type(&par.typ)?;

if arg_type != par_type {
return Err(CompilerError::new(
Expand Down
14 changes: 9 additions & 5 deletions src/compiler/function_declaration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,25 @@ impl Program {
};

let old_stack_pos = self.stack_pos;
let return_type = fdec.return_type.as_ref().map(|t| self.get_variable_type(t));
let return_type = fdec
.return_type
.as_ref()
.map(|t| self.get_variable_type(t))
.transpose()?;

let body = self.with_function_scope(return_type.clone(), |this| {
let parameters = fdec
.parameters
.iter()
.rev()
.map(|parameter| {
(
Ok((
parameter.identifier.clone(),
parameter.pos.clone(),
this.get_variable_type(&parameter.typ),
)
this.get_variable_type(&parameter.typ)?,
))
})
.collect::<Vec<_>>();
.collect::<Result<Vec<_>, CompilerError>>()?;

let ProgramScope::FunctionScope(function_scope) = &mut this.scope else {
unreachable!();
Expand Down
52 changes: 49 additions & 3 deletions src/compiler/program.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use phf::phf_map;
use std::collections::HashMap;

use super::{
Expand All @@ -12,7 +13,26 @@ use super::{
},
};

use crate::{lexer::Keyword, parser::definition::Declaration};
use crate::{
lexer::Keyword,
parser::{
definition::Declaration,
types::{Type, TypeIdentifier},
},
};

pub struct SystemCallDefinition {
pub returns: Option<Type>,
}

pub static SYSTEM_CALLS: phf::Map<&'static str, SystemCallDefinition> = phf_map! {
"printf" => SystemCallDefinition {
returns: None,
},
"malloc" => SystemCallDefinition {
returns: Some(Type { identifier: TypeIdentifier::Primitive(Keyword::Pointer), identifier_pos: 0..0, pos: 0..0, children: None })
},
};

#[derive(Debug)]
pub struct Program {
Expand Down Expand Up @@ -106,7 +126,33 @@ impl Program {
Ok(result)
}

fn add_system_calls(&mut self) {
for system_call in SYSTEM_CALLS.into_iter() {

}

self.functions.push(Function {
body,
parameters: fdec.parameters.clone(),
return_type,
identifier_pos: fdec.identifier_pos.clone(),
});

let function_location = self.functions.len() - 1;

// Pseudo-type-ish variable, does not exist on the stack.
self.create_variable(
fdec.identifier.clone(),
Variable {
pos: statement.pos.clone(),
typ: VariableType::Function(function_location),
},
);
}

pub fn compile(mut self, parsed: Vec<Declaration>) -> Result<Program, CompilerError> {
self.add_system_calls();

// Compile main program
let procedures = self.get_procedures(&parsed)?;

Expand Down Expand Up @@ -140,8 +186,8 @@ impl Program {
let params = &main_func
.parameters
.iter()
.map(|v| (self.get_variable_type(&v.typ), v.pos.clone()))
.collect::<Vec<_>>()[..];
.map(|v| Ok((self.get_variable_type(&v.typ)?, v.pos.clone())))
.collect::<Result<Vec<_>, CompilerError>>()?[..];

self.main_func_nparams = match params {
[] => 0,
Expand Down
39 changes: 16 additions & 23 deletions src/compiler/scope/variable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{
ops::{Deref, Range},
};

use crate::lexer::Keyword;
use crate::{lexer::Keyword, parser::types::Type};

/// Intermediate representation of a variable.
/// This type represents what the user wants to save,
Expand All @@ -17,7 +17,7 @@ pub struct Variable {
#[derive(Debug, Clone, PartialEq)]
pub struct StructType {
pub id: usize,
pub identifier: String,
pub typ: Type,
pub size: usize, // size in bytes
}

Expand All @@ -29,6 +29,20 @@ pub enum VariableType {
Struct(StructType),
}

impl Display for VariableType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
VariableType::Pointer(pointer) => {
write!(f, "*")?;
pointer.fmt(f)
}
VariableType::Value(keyword) => keyword.fmt(f),
VariableType::Struct(struc) => struc.typ.fmt(f),
_ => write!(f, "{self:?}"),
}
}
}

#[derive(Debug, Clone)]
pub enum VariableLocation {
// The stack position will be negative for
Expand Down Expand Up @@ -57,24 +71,3 @@ impl Deref for StoredVariable {
&self.variable
}
}

impl Display for VariableType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
VariableType::Pointer(pointer) => {
write!(f, "*")?;
pointer.fmt(f)
}
VariableType::Value(value) => {
let v = match value {
Keyword::Int => "int",
Keyword::Bool => "bool",
_ => return write!(f, "{value:?}"),
};

write!(f, "{v}")
}
_ => write!(f, "{self:?}"),
}
}
}
7 changes: 4 additions & 3 deletions src/compiler/struct_declaration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl Program {

// Do it in reverse since the stack grows that way
for (identifier, field) in sdec.fields.iter().rev() {
let typ = self.get_variable_type(&field.typ);
let typ = self.get_variable_type(&field.typ)?;
let size = Self::get_type_size(&typ);

fields.insert(
Expand All @@ -55,12 +55,13 @@ impl Program {

// Pseudo-type-ish variable, does not exist on the stack.
self.create_variable(
sdec.identifier.clone(),
sdec.typ.get_identifier().unwrap().into(),
Variable {
pos: statement.pos.clone(),
typ: VariableType::Struct(StructType {
id: struct_id,
identifier: sdec.identifier.clone(),
typ: sdec.typ.clone(),
// identifier: sdec.identifier.clone(),
size: struct_size,
}),
},
Expand Down
16 changes: 12 additions & 4 deletions src/compiler/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ impl Program {
}
}

pub fn get_variable_type(&self, typ: &Type) -> VariableType {
pub fn get_variable_type(&self, typ: &Type) -> Result<VariableType, CompilerError> {
match typ.identifier {
TypeIdentifier::Primitive(Keyword::Pointer) => {
let Some(children) = &typ.children else {
Expand All @@ -124,10 +124,18 @@ impl Program {
}

let inner = children.get(0).unwrap();
VariableType::Pointer(Box::new(self.get_variable_type(inner)))
Ok(VariableType::Pointer(Box::new(
self.get_variable_type(inner)?,
)))
}
TypeIdentifier::Primitive(primitive) => Ok(VariableType::Value(primitive)),
TypeIdentifier::Struct(ref s) => {
let Some(variable) = self.get_variable(s) else {
return Err(CompilerError::new(typ.identifier_pos.clone(), CompilerErrorKind::UnknownType(s.into())));
};

Ok(variable.typ.clone())
}
TypeIdentifier::Primitive(primitive) => VariableType::Value(primitive),
TypeIdentifier::Struct(ref s) => self.get_variable(s).unwrap().typ.clone(),
}
}

Expand Down
14 changes: 13 additions & 1 deletion src/lexer/definition.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::ops::Range;
use std::{fmt::Display, ops::Range};

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Keyword {
Expand Down Expand Up @@ -44,6 +44,18 @@ pub enum Keyword {
Comment,
}

impl Display for Keyword {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let v = match self {
Keyword::Int => "int",
Keyword::Bool => "bool",
_ => return write!(f, "{self:?}"),
};

write!(f, "{v}")
}
}

#[derive(Debug, PartialEq, Clone)]
pub enum Literal {
String(String),
Expand Down
Loading

0 comments on commit 2ea2262

Please sign in to comment.