Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: Nickforall/ijssel
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: Nickforall/ijssel
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: type-checker
Choose a head ref
Able to merge. These branches can be automatically merged.
  • 4 commits
  • 20 files changed
  • 1 contributor

Commits on May 5, 2020

  1. Copy the full SHA
    7395139 View commit details

Commits on May 6, 2020

  1. Typesystem basics

    Nickforall committed May 6, 2020
    Copy the full SHA
    2e298e5 View commit details

Commits on May 8, 2020

  1. Parsing list types

    Nickforall committed May 8, 2020
    Copy the full SHA
    41fbed5 View commit details

Commits on May 9, 2020

  1. Parse array expressions

    Nickforall committed May 9, 2020
    Copy the full SHA
    74b6ed9 View commit details
23 changes: 17 additions & 6 deletions src/codegen/function.rs
Original file line number Diff line number Diff line change
@@ -3,21 +3,27 @@ use crate::raw_cstr;
use llvm_sys::core::*;
use llvm_sys::prelude::*;
use std::collections::HashMap;
use std::convert::From;

pub fn compile_function(module: &LLVMModuleRef, expression: &FunctionExpression) {
let args_count = expression.arguments.len();
let mut args: Vec<LLVMTypeRef> = Vec::with_capacity(args_count);
let arg_type: *mut *mut llvm_sys::LLVMType = {
for _arg in &expression.arguments {
for arg in &expression.arguments {
// TODO: types
args.push(unsafe { LLVMInt32Type() });
args.push(LLVMTypeRef::from(&arg.input_type));
}

args.as_mut_ptr()
};

let function_type = unsafe {
let fn_type = LLVMFunctionType(LLVMInt32Type(), arg_type, args.len() as u32, 0);
let fn_type = LLVMFunctionType(
LLVMTypeRef::from(&expression.body.return_type),
arg_type,
args.len() as u32,
0,
);
fn_type
};

@@ -46,16 +52,21 @@ pub fn compile_extern_function(module: &LLVMModuleRef, expression: &ExternFuncti
let args_count = expression.arguments.len();
let mut args: Vec<LLVMTypeRef> = Vec::with_capacity(args_count);
let arg_type: *mut *mut llvm_sys::LLVMType = {
for _arg in &expression.arguments {
for arg in &expression.arguments {
// TODO: types
args.push(unsafe { LLVMInt32Type() });
args.push(LLVMTypeRef::from(&arg.input_type));
}

args.as_mut_ptr()
};

let function_type = unsafe {
let fn_type = LLVMFunctionType(LLVMInt32Type(), arg_type, args.len() as u32, 0);
let fn_type = LLVMFunctionType(
LLVMTypeRef::from(&expression.return_type),
arg_type,
args.len() as u32,
0,
);
fn_type
};

8 changes: 5 additions & 3 deletions src/codegen/mod.rs
Original file line number Diff line number Diff line change
@@ -4,13 +4,15 @@ pub mod call;
pub mod constants;
pub mod function;
pub mod module;
pub mod types;
pub mod variable;

pub use block::CodegenBlock;
use llvm_sys::prelude::*;

use crate::modules::Module;
use crate::parser::Expression;
use crate::parser::Module;
use llvm_sys::prelude::*;

pub use block::CodegenBlock;

pub fn compile_application(module: Module) -> LLVMModuleRef {
self::module::compile_module(&module)
14 changes: 6 additions & 8 deletions src/codegen/module.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::parser::{Expression, Module};
use crate::modules::{Module, ModuleFunction};

use llvm_sys::core::*;
use llvm_sys::prelude::*;
@@ -7,14 +7,12 @@ pub fn compile_module(module: &Module) -> LLVMModuleRef {
let module_name = crate::raw_cstr(module.name.as_str());
let llvm_module = unsafe { LLVMModuleCreateWithName(module_name) };

for expression in &module.expressions {
match expression {
Expression::Function(expr) => super::function::compile_function(&llvm_module, &**expr),
Expression::ExternFunction(expr) => {
super::function::compile_extern_function(&llvm_module, &**expr)
for (_, func) in &module.functions {
match func {
ModuleFunction::Local(expr) => super::function::compile_function(&llvm_module, &expr),
ModuleFunction::External(expr) => {
super::function::compile_extern_function(&llvm_module, &expr)
}

expr => panic!("Incorrect module level expression {:?}", expr),
}
}

25 changes: 25 additions & 0 deletions src/codegen/types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use crate::parser::Type;
use llvm_sys::core::{LLVMArrayType, LLVMInt32Type};
use llvm_sys::prelude::LLVMTypeRef;

use std::convert::From;

impl From<Type> for LLVMTypeRef {
fn from(value: Type) -> LLVMTypeRef {
Self::from(&value)
}
}

impl From<&Type> for LLVMTypeRef {
fn from(value: &Type) -> LLVMTypeRef {
match value {
Type::Int32 => unsafe { LLVMInt32Type() },
Type::Unknown => panic!("Could not infer type, got Unknown."),
Type::ListOf(t, length) => {
let inner_type = LLVMTypeRef::from(t.as_ref());
unsafe { LLVMArrayType(inner_type, *length) }
}
_ => unimplemented!(),
}
}
}
6 changes: 5 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
@@ -11,7 +11,9 @@ use std::time::Instant;

mod codegen;
mod machine;
mod modules;
mod parser;
mod type_system;

use self::parser::parser::Parser;
use self::parser::tokenizer::Tokenizer;
@@ -70,6 +72,8 @@ fn main() {
return;
}

let module = modules::Module::from_ast_module(parser.module);

let extension = match matches.value_of("file-type").unwrap_or("object") {
"asm" => "s",
"bc" => "bc",
@@ -83,7 +87,7 @@ fn main() {
.expect("Invalid default output"),
);

let llvm_module = codegen::compile_application(parser.module);
let llvm_module = codegen::compile_application(module);

if matches.value_of("file-type").unwrap_or("object") == "ll" {
unsafe { llvm_sys::core::LLVMDumpModule(llvm_module) };
17 changes: 17 additions & 0 deletions src/modules/function.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use crate::parser::{Expression, ExternFunctionExpression, FunctionExpression};
use std::convert::From;

pub enum ModuleFunction {
Local(FunctionExpression),
External(ExternFunctionExpression),
}

impl From<&Expression> for ModuleFunction {
fn from(value: &Expression) -> Self {
match value {
Expression::Function(expr) => ModuleFunction::Local(expr.as_ref().clone()),
Expression::ExternFunction(expr) => ModuleFunction::External(expr.as_ref().clone()),
_ => panic!("Invalid top level expression"),
}
}
}
5 changes: 5 additions & 0 deletions src/modules/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub mod function;
pub mod module;

pub use function::ModuleFunction;
pub use module::Module;
33 changes: 33 additions & 0 deletions src/modules/module.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use super::ModuleFunction;
use crate::parser::{AstModule, Expression};
use std::collections::HashMap;

pub struct Module {
pub functions: HashMap<String, ModuleFunction>,
pub name: String,
}

impl Module {
pub fn from_ast_module(module: AstModule) -> Self {
let mut functions = HashMap::new();

for expression in module.expressions {
let (name, expr) = match expression {
Expression::Function(ref internal) => {
(internal.name.clone(), ModuleFunction::from(&expression))
}
Expression::ExternFunction(ref internal) => {
(internal.name.clone(), ModuleFunction::from(&expression))
}
_ => panic!("Invalid top-level expression"),
};

functions.insert(name, expr);
}

Module {
functions,
name: module.name,
}
}
}
62 changes: 46 additions & 16 deletions src/parser/expression.rs
Original file line number Diff line number Diff line change
@@ -1,59 +1,77 @@
use super::tokenizer::BinaryOperator;
use super::Type;

#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct NumberLiteralExpression {
pub number: f64,
pub return_type: Type,
}

impl NumberLiteralExpression {
pub fn new(number: f64) -> Self {
NumberLiteralExpression { number }
NumberLiteralExpression {
number,
return_type: Type::Int32,
}
}
}

#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct VariableExpression {
pub binding: String,
pub return_type: Type,
}

impl VariableExpression {
pub fn new(binding: String) -> Self {
VariableExpression { binding }
VariableExpression {
binding,
return_type: Type::Unknown,
}
}
}

#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct BlockExpression {
pub expressions: Vec<Expression>,
pub return_type: Type,
}

impl BlockExpression {
pub fn new(expressions: Vec<Expression>) -> Self {
BlockExpression { expressions }
pub fn new(expressions: Vec<Expression>, return_type: Type) -> Self {
BlockExpression {
expressions,
return_type,
}
}
}

#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct FunctionExpression {
pub name: String,
pub body: BlockExpression,
pub arguments: Vec<FunctionArgument>,
}

#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct ExternFunctionExpression {
pub name: String,
pub arguments: Vec<FunctionArgument>,
pub return_type: Type,
}

#[derive(Clone, Debug)]
pub struct FunctionArgument {
pub binding_name: String,
pub input_type: Type,
}

impl FunctionArgument {
pub fn new(binding_name: String) -> Self {
Self { binding_name }
pub fn new(binding_name: String, input_type: Type) -> Self {
Self {
binding_name,
input_type,
}
}
}

@@ -68,15 +86,16 @@ impl FunctionExpression {
}

impl ExternFunctionExpression {
pub fn new(name: &str, args: Vec<FunctionArgument>) -> Self {
pub fn new(name: &str, args: Vec<FunctionArgument>, return_type: Type) -> Self {
Self {
name: String::from(name),
arguments: args,
return_type,
}
}
}

#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct CallExpression {
pub function_name: String,
pub args: Vec<Expression>,
@@ -91,7 +110,7 @@ impl CallExpression {
}
}

#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct BinaryExpression {
pub left: Expression,
pub right: Expression,
@@ -108,13 +127,24 @@ impl BinaryExpression {
}
}

#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct ArrayExpression {
pub values: Vec<Expression>,
}

impl ArrayExpression {
pub fn new(values: Vec<Expression>) -> Self {
Self { values }
}
}

#[derive(Clone, Debug)]
pub enum Expression {
Function(Box<FunctionExpression>),
ExternFunction(Box<ExternFunctionExpression>),
Binary(Box<BinaryExpression>),
NumberLiteral(Box<NumberLiteralExpression>),
Variable(Box<VariableExpression>),
Call(Box<CallExpression>),
// Block(Box<BlockExpression>),
Array(Box<ArrayExpression>),
}
4 changes: 3 additions & 1 deletion src/parser/mod.rs
Original file line number Diff line number Diff line change
@@ -2,10 +2,12 @@ pub mod expression;
pub mod module;
pub mod parser;
pub mod tokenizer;
pub mod types;

pub use expression::{
BinaryExpression, BlockExpression, CallExpression, Expression, ExternFunctionExpression,
FunctionExpression, NumberLiteralExpression, VariableExpression,
};

pub use module::Module;
pub use module::AstModule;
pub use types::Type;
4 changes: 2 additions & 2 deletions src/parser/module.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use super::Expression;

#[derive(Debug)]
pub struct Module {
pub struct AstModule {
pub name: String,
pub expressions: Vec<Expression>,
}

impl Module {
impl AstModule {
pub fn new() -> Self {
Self {
name: String::from("Main"),
Loading