Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add structs #1

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading