Skip to content

Commit

Permalink
Add varargs
Browse files Browse the repository at this point in the history
  • Loading branch information
didrikmunther committed Sep 20, 2024
1 parent 086bee7 commit e494b1b
Show file tree
Hide file tree
Showing 22 changed files with 303 additions and 156 deletions.
8 changes: 3 additions & 5 deletions input.ro
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
__builtin fn printf(format: str, ...args: any);

fn add_two_numbers(a: int, b: int) {
let c = a + b;

Expand All @@ -6,9 +8,5 @@ fn add_two_numbers(a: int, b: int) {

let a = 1;
let b = 2;
let u = add_two_numbers(
a,
b
);

let q = u + 1;
add_two_numbers(a, b);
2 changes: 1 addition & 1 deletion lsp-client/syntaxes/rost.tmLanguage.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
},
{
"name": "keyword.control.rost",
"match": "\\b(pub|let|fn|if|else|for|while|return)\\b"
"match": "\\b(__builtin|pub|let|fn|if|else|for|while|return)\\b"
},
{
"name": "string.quoted.double.rost",
Expand Down
35 changes: 15 additions & 20 deletions out.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
def __compiler__with_regular_args(func):
def wrapper(*args):
n_args = __stack.pop()
args = reversed([__stack.pop() for i in range(n_args)])
args = [__stack.pop() for i in range(n_args)]
__stack.append(func(*args))

return wrapper
Expand Down Expand Up @@ -45,41 +45,36 @@ def __intrinsic__stack_pop():
# boilerplate_start end

def __user__printf():
__intrinsic__stack_pop()
_0_format = __intrinsic__stack_pop()

__builtin__printf()
def __user__add_two_numbers():
__intrinsic__stack_pop()
_2_a = __intrinsic__stack_pop()
_3_b = __intrinsic__stack_pop()
__intrinsic__stack_push(_3_b)
__intrinsic__stack_push(_2_a)
_3_a = __intrinsic__stack_pop()
_4_b = __intrinsic__stack_pop()
__intrinsic__stack_push(_4_b)
__intrinsic__stack_push(_3_a)
__intrinsic__stack_add()
_4_c = __intrinsic__stack_pop()
_5_c = __intrinsic__stack_pop()
__intrinsic__stack_push(_5_c)
__intrinsic__stack_push(_4_b)
__intrinsic__stack_push(_3_a)
__intrinsic__stack_push(__global_data[0])
__intrinsic__stack_push(_2_a)
__intrinsic__stack_push(_3_b)
__intrinsic__stack_push(_4_c)
__intrinsic__stack_push(4)
__user__printf()
__intrinsic__stack_pop()


def __setup():
global __global_data
__global_data = list(range(2))
__global_data = list(range(1))
__global_data[0] = "%i + %i = %i\n"
__global_data[1] = "a"

def __main():
__intrinsic__stack_push(1)
_6_a = __intrinsic__stack_pop()
_7_a = __intrinsic__stack_pop()
__intrinsic__stack_push(2)
_7_b = __intrinsic__stack_pop()
__intrinsic__stack_push(_6_a)
__intrinsic__stack_push(__global_data[1])
__intrinsic__stack_push(_7_b)
__intrinsic__stack_add()
_8_b = __intrinsic__stack_pop()
__intrinsic__stack_push(_8_b)
__intrinsic__stack_push(_7_a)
__intrinsic__stack_push(2)
__user__add_two_numbers()
__intrinsic__stack_pop()
Expand Down
2 changes: 1 addition & 1 deletion src/backend/python/boilerplate_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
def __compiler__with_regular_args(func):
def wrapper(*args):
n_args = __stack.pop()
args = reversed([__stack.pop() for i in range(n_args)])
args = [__stack.pop() for i in range(n_args)]
__stack.append(func(*args))

return wrapper
Expand Down
21 changes: 16 additions & 5 deletions src/backend/python/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use crate::{
compiler::program::{
builder::Builder,
ir::{
InstructionKind, PrimitiveValue, ProcedureCall, ValueKind, VariableKind, VariableScope,
FunctionBody, InstructionKind, PrimitiveValue, ProcedureCall, ValueKind, VariableKind,
VariableScope,
},
Program,
},
Expand Down Expand Up @@ -50,10 +51,20 @@ impl Generator {
});

for (function, identifier) in functions {
elements.push(Element::FunctionDefinition {
identifier: format!("__user__{identifier}"),
content: Box::new(self.get_program(&function.body, program)?),
});
match &function.body {
FunctionBody::Builtin => {
elements.push(Element::FunctionDefinition {
identifier: format!("__user__{identifier}"),
content: Box::new(Element::Raw(format!("__builtin__{identifier}()"))),
});
}
FunctionBody::Block(block) => {
elements.push(Element::FunctionDefinition {
identifier: format!("__user__{identifier}"),
content: Box::new(self.get_program(block, program)?),
});
}
}
}

Ok(elements)
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/program/function_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ impl Program {
) -> Result<Builder, CompilerError> {
let mut builder = Builder::new();

for arg in &fcall.args {
for arg in fcall.args.iter().rev() {
let result = self.handle_expression(arg);
if let Some(expr) = self.get_or_add_error(result) {
builder = builder.append(expr);
Expand Down Expand Up @@ -64,6 +64,7 @@ impl Program {
},
));
}
_ if function.vararg_parameter.is_some() && parameter_diff < 0 => {}
_ if parameter_diff < 0 => {
return Err(CompilerError::new(
fcall.left.pos.clone(),
Expand Down
95 changes: 69 additions & 26 deletions src/compiler/program/function_declaration.rs
Original file line number Diff line number Diff line change
@@ -1,71 +1,114 @@
use super::{
builder::Builder,
ir::{
Function, Instruction, InstructionKind, NormalVariable, PrimitiveType, Variable,
VariableKind, VariableScope,
Function, FunctionBody, Instruction, InstructionKind, NormalVariable, PrimitiveType,
Variable, VariableKind, VariableScope,
},
Program,
};
use crate::{
compiler::error::CompilerError,
parser::definition::{Declaration, FunctionDeclaration},
parser::definition::{Declaration, FunctionDeclaration, FunctionDeclarationContent},
};

fn add_function_parameters(this: &mut Program, fdec: &FunctionDeclaration) -> Vec<usize> {
let mut parameter_variable_ids = Vec::new();

for param in &fdec.parameters {
let variable_id = this.insert_variable(Variable {
identifier: param.identifier.clone(),
scope: VariableScope::Local,
kind: VariableKind::Normal(NormalVariable {
typ: PrimitiveType::Int, // TODO: Get the actual type
}),
declaration_pos: param.pos.clone(),
assignment_has_error: false,
});

parameter_variable_ids.push(variable_id);
}

if let Some(vararg_parameter) = &fdec.vararg_parameter {
let variable_id = this.insert_variable(Variable {
identifier: vararg_parameter.identifier.clone(),
scope: VariableScope::Local,
kind: VariableKind::Normal(NormalVariable {
typ: PrimitiveType::Int, // TODO: Get the actual type
}),
declaration_pos: vararg_parameter.pos.clone(),
assignment_has_error: false,
});

parameter_variable_ids.push(variable_id);
}

parameter_variable_ids
}

impl Program {
pub fn create_function_declaration(
&mut self,
fdec: &FunctionDeclaration,
) -> Result<(), CompilerError> {
let mut parameter_variable_ids = Vec::new();
let block = match &fdec.content {
FunctionDeclarationContent::Builtin => {
let parameter_variable_ids = add_function_parameters(self, fdec);

self.insert_variable(Variable {
identifier: fdec.identifier.clone(),
scope: VariableScope::Global,
kind: VariableKind::DeclaredFunction(Function {
vararg_parameter: parameter_variable_ids.last().copied(),
parameter_variable_ids,
body: FunctionBody::Builtin,
}),
declaration_pos: fdec.identifier_pos.clone(),
assignment_has_error: false,
});

return Ok(());
}
FunctionDeclarationContent::Block(block) => block,
};

let result = self.with_scope(|this| {
let location = block.iter().fold(fdec.identifier_pos.clone(), |acc, decl| {
acc.start..decl.pos.end
});

// The first value on the stack on a function call is always amount of arguments.
// This is used for varargs functions, but we don't have those yet.
let mut body = Builder::new().push(Instruction::new(
fdec.identifier_pos.clone(),
InstructionKind::Pop,
));

let location = fdec
.content
.iter()
.fold(fdec.identifier_pos.clone(), |acc, decl| {
acc.start..decl.pos.end
});

for param in &fdec.parameters {
let variable_id = this.insert_variable(Variable {
identifier: param.identifier.clone(),
scope: VariableScope::Local,
kind: VariableKind::Normal(NormalVariable {
typ: PrimitiveType::Int, // TODO: Get the actual type
}),
declaration_pos: param.pos.clone(),
assignment_has_error: false,
});

parameter_variable_ids.push(variable_id);
let parameter_variable_ids = add_function_parameters(this, fdec);

for (&variable_id, param) in parameter_variable_ids.iter().zip(fdec.parameters.iter()) {
body = body.push(Instruction::new(
param.pos.clone(),
InstructionKind::Assign(variable_id),
));
}

let body = body.append(this.get_instructions(&fdec.content)?);
let body = body.append(this.get_instructions(block)?);

Ok((body, location))
Ok(((body, parameter_variable_ids), location))
});

let body = self.get_or_add_error(result);
let assignment_has_error = body.is_none();

let (body, parameter_variable_ids) = body.unwrap_or_default();

self.insert_variable(Variable {
identifier: fdec.identifier.clone(),
scope: VariableScope::Global,
kind: VariableKind::DeclaredFunction(Function {
parameter_variable_ids,
body: body.unwrap_or_default(),
body: FunctionBody::Block(body),
vararg_parameter: None,
}),
declaration_pos: fdec.identifier_pos.clone(),
assignment_has_error,
Expand Down
11 changes: 9 additions & 2 deletions src/compiler/program/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,17 @@ pub struct NormalVariable {
pub typ: PrimitiveType,
}

#[derive(Debug, Default)]
#[derive(Debug)]
pub enum FunctionBody {
Builtin,
Block(Builder),
}

#[derive(Debug)]
pub struct Function {
pub parameter_variable_ids: Vec<VariableId>,
pub body: Builder,
pub vararg_parameter: Option<VariableId>,
pub body: FunctionBody,
}

#[derive(Debug)]
Expand Down
40 changes: 19 additions & 21 deletions src/compiler/program/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
use super::error::CompilerError;
use crate::parser::{
definition::{Declaration, FunctionDeclaration, FunctionDeclarationParameter},
types::{Type, TypeIdentifier},
};
use crate::parser::definition::Declaration;
use builder::Builder;
use ir::{PrimitiveValue, Variable};
use rust_lapper::Lapper;
Expand Down Expand Up @@ -57,9 +54,9 @@ impl Program {
}
}

pub fn get_or_add_error(&mut self, result: Result<Builder, CompilerError>) -> Option<Builder> {
pub fn get_or_add_error<T>(&mut self, result: Result<T, CompilerError>) -> Option<T> {
match result {
Ok(builder) => Some(builder),
Ok(v) => Some(v),
Err(error) => {
self.errors.push(error);
None
Expand All @@ -68,21 +65,22 @@ impl Program {
}

fn add_builtin_functions(&mut self) -> Result<(), CompilerError> {
self.create_function_declaration(&FunctionDeclaration {
identifier: "printf".to_string(),
identifier_pos: 0..0,
parameters: vec![FunctionDeclarationParameter {
identifier: "format".to_string(),
typ: Type {
identifier: TypeIdentifier::Identifier("string".to_string()),
pos: 0..0,
children: None,
},
pos: 0..0,
}],
content: vec![],
return_type: None,
})?;
// self.create_function_declaration(&FunctionDeclaration {
// identifier: "printf".to_string(),
// identifier_pos: 0..0,
// parameters: vec![FunctionDeclarationParameter {
// identifier: "format".to_string(),
// typ: Type {
// identifier: TypeIdentifier::Identifier("string".to_string()),
// pos: 0..0,
// children: None,
// },
// pos: 0..0,
// }],
// content: vec![],
// return_type: None,
// builtin: true,
// })?;

Ok(())
}
Expand Down
5 changes: 2 additions & 3 deletions src/compiler/program/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use rust_lapper::{Interval, Lapper};
use crate::compiler::error::CompilerError;

use super::{
builder::Builder,
ir::{VariableId, VariableScope},
Location, Program,
};
Expand Down Expand Up @@ -56,9 +55,9 @@ impl Program {

/// Used when entering a new scope, makes sure that variables are properly scoped.
/// Inner function should return the new builder and the range of the location of the scope.
pub fn with_scope<F>(&mut self, inner: F) -> Result<Builder, CompilerError>
pub fn with_scope<F, T>(&mut self, inner: F) -> Result<T, CompilerError>
where
F: FnOnce(&mut Self) -> Result<(Builder, Range<Location>), CompilerError>,
F: FnOnce(&mut Self) -> Result<(T, Range<Location>), CompilerError>,
{
let old_scope_id = self.scope_id;
let scope_id = self.scopes.len();
Expand Down
Loading

0 comments on commit e494b1b

Please sign in to comment.