WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.7% of users enabled 2FA.

Commit a1cb83e3 authored by Eduardo Souza's avatar Eduardo Souza
Browse files

Adding mutable variables (wip)

parent 01907662
use crate::generator::Context;
use crate::generator::{Context, create_block_alloca};
use crate::mu_generator::*;
use llvm_sys::core::*;
use llvm_sys::prelude::LLVMValueRef;
......@@ -177,6 +177,26 @@ impl BinaryExp {
}
}
#[derive(Clone)]
pub struct VarExp {
vars: Vec<(Var, Box<dyn Exp>)>,
body_exp: Box<dyn Exp>,
}
impl VarExp {
pub fn vars(&self) -> &Vec<(Var, Box<dyn Exp>)> {
&self.vars
}
pub fn body_exp(&self) -> &Box<dyn Exp> {
&self.body_exp
}
pub fn new(vars: Vec<(Var, Box<dyn Exp>)>, body_exp: Box<dyn Exp>) -> VarExp {
VarExp { vars, body_exp }
}
}
#[derive(Clone)]
pub struct Prototype {
name: String,
......@@ -258,10 +278,36 @@ where
}
}
impl Exp for VarExp {
fn print(&self) -> String {
let mut assigned_exps = vec![];
for (var, exp) in &self.vars {
assigned_exps.push(format!("Assign({}, {})", var.print(), exp.print()));
};
format!("VarExp({:?}, {})", assigned_exps, self.body_exp.print())
}
unsafe fn code_gen(
&self,
module: &*mut LLVMModule,
context: &mut Context,
) -> Result<*mut LLVMValue, String> {
unimplemented!()
}
unsafe fn code_gen_mu(
&self,
vm: &mut Mu_VM,
fun_ver: &mut MuFunctionVersion,
) -> Result<Arc<TreeNode>, String> {
unimplemented!()
}
}
impl Exp for ForExp {
fn print(&self) -> String {
format!(
"ForExpr({:?}, {:?}, {:?}, {:?}, {:?})",
"ForExpr({}, {}, {}, {}, {})",
self.var.print(),
self.start_exp.print(),
self.end_exp.print(),
......@@ -291,21 +337,24 @@ impl Exp for ForExp {
LLVMBuildBr(context.builder, preloop_block);
LLVMPositionBuilderAtEnd(context.builder, preloop_block);
let mut phi = LLVMBuildPhi(
context.builder,
context.ty,
self.var.name().as_str().as_ptr() as *const c_char,
);
LLVMAddIncoming(
phi,
vec![start_exp].as_mut_slice().as_mut_ptr(),
vec![preheader_block].as_mut_slice().as_mut_ptr(),
1 as c_uint,
);
// let mut phi = LLVMBuildPhi(
// context.builder,
// context.ty,
// self.var.name().as_str().as_ptr() as *const c_char,
// );
//
// LLVMAddIncoming(
// phi,
// vec![start_exp].as_mut_slice().as_mut_ptr(),
// vec![preheader_block].as_mut_slice().as_mut_ptr(),
// 1 as c_uint,
// );
let variable = create_block_alloca(context, preheader_block, self.var.name.clone().as_str());
LLVMBuildStore(context.builder,start_exp, variable);
let old_value = context.named_values.remove(self.var.name());
context.named_values.insert(self.var.name().clone(), phi);
context.named_values.insert(self.var.name().clone(), variable);
let end_exp: *mut LLVMValue = match self.end_exp().code_gen(module, context) {
Ok(result) => result,
......@@ -345,20 +394,22 @@ impl Exp for ForExp {
e @ Err(_) => return e,
};
let cur_value = LLVMBuildLoad(context.builder,variable, self.var.name.clone().as_str().as_ptr() as *const c_char);
let next_value = LLVMBuildFAdd(
context.builder,
phi,
cur_value,
step_exp,
"nextvar\0".as_ptr() as *const c_char,
);
LLVMBuildStore(context.builder, next_value, variable);
let loop_end_block = LLVMGetInsertBlock(context.builder);
LLVMAddIncoming(
phi,
vec![next_value].as_mut_slice().as_mut_ptr(),
vec![loop_block].as_mut_slice().as_mut_ptr(),
1 as c_uint,
);
// LLVMAddIncoming(
// phi,
// vec![next_value].as_mut_slice().as_mut_ptr(),
// vec![loop_block].as_mut_slice().as_mut_ptr(),
// 1 as c_uint,
// );
LLVMBuildBr(context.builder, preloop_block);
......@@ -1107,7 +1158,11 @@ impl Exp for Var {
context: &mut Context,
) -> Result<*mut LLVMValue, String> {
match context.named_values.get(self.name()) {
Some(val) => Ok(*val),
Some(val) => {
let name = format!("{}\0", self.name.clone());
println!("{}", name);
let var = LLVMBuildLoad( context.builder, *val, name.as_str().as_ptr() as *const c_char);
Ok(var)},
None => Err(String::from("Unknown variable name.")),
}
}
......
......@@ -17,7 +17,7 @@ use self::llvm::execution_engine::{
LLVMFreeMachineCodeForFunction, LLVMGenericValueToFloat, LLVMInitializeMCJITCompilerOptions,
LLVMLinkInMCJIT, LLVMMCJITCompilerOptions, LLVMOpaqueExecutionEngine, LLVMRunFunction,
};
use self::llvm::prelude::{LLVMBool, LLVMBuilderRef, LLVMContextRef};
use self::llvm::prelude::{LLVMBool, LLVMBuilderRef, LLVMContextRef, LLVMBasicBlockRef};
use self::llvm::support::LLVMAddSymbol;
use self::llvm::target::{LLVM_InitializeNativeAsmPrinter, LLVM_InitializeNativeTarget};
use self::llvm::target_machine::{
......@@ -104,7 +104,7 @@ unsafe fn run_function(
f,
LLVMRunFunction(ee, f, args.len() as c_uint, args.as_mut_ptr()),
),
Err(e) => return Err(e)
Err(e) => return Err(e),
};
let triple = LLVMGetDefaultTargetTriple();
......@@ -188,7 +188,7 @@ pub unsafe fn code_gen(filename: String, nodes: ASTNodes) -> Vec<Result<f64, Str
}
let module = llvm::core::LLVMModuleCreateWithName(filename.as_str().as_ptr() as *const _);
let context = Context::new();
};
}
returning_values
}
......@@ -272,6 +272,13 @@ pub fn get_function_by_name(function: *mut LLVMModule, name: &str) -> Option<*mu
}
}
pub unsafe fn create_block_alloca(context : &mut Context, block : LLVMBasicBlockRef, var_name : &str) -> LLVMValueRef {
let builder = LLVMCreateBuilder();
let fi = LLVMGetFirstInstruction(block);
LLVMPositionBuilder(builder, block, fi);
LLVMBuildAlloca(builder, context.ty, var_name.as_ptr() as *const c_char)
}
impl Code_gen for Function {
unsafe fn code_gen(
&self,
......@@ -295,7 +302,9 @@ impl Code_gen for Function {
// set function parameters
for (param, arg) in get_params(function).iter().zip(self.proto().args()) {
context.named_values.insert(arg.clone(), *param);
let arg_alloca = create_block_alloca(context, basic_block, arg.clone().as_str());
LLVMBuildStore(context.builder, *param, arg_alloca);
context.named_values.insert(arg.clone(), arg_alloca);
}
let body = match self.body().code_gen(module, context) {
......
use std::env::var;
use std::ops::Add;
use std::{fs, io};
......@@ -14,6 +15,7 @@ pub enum Token {
ELSE,
FOR,
IN,
VAR,
}
pub fn read_file() -> (String, Vec<Token>) {
......@@ -121,6 +123,7 @@ fn parse_identifier_or_keyword(c: char, input_str: &[u8], index: &mut i32) -> To
let else_token = String::from("else");
let for_token = String::from("for");
let in_token = String::from("in");
let var_token = String::from("var");
if result.eq(&def_token) {
return Token::DEF;
......@@ -150,6 +153,10 @@ fn parse_identifier_or_keyword(c: char, input_str: &[u8], index: &mut i32) -> To
return Token::ELSE;
}
if result.eq(&var_token) {
return Token::VAR;
}
Token::ID(result)
}
//
......
......@@ -11,4 +11,3 @@ pub mod parser;
pub mod mu_generator;
pub mod tests;
......@@ -38,7 +38,7 @@ fn main() {
for value in values {
match value {
Ok(v) => println!("{}", v),
Err(e) => println!("{}", e)
Err(e) => println!("{}", e),
}
}
}
......@@ -136,6 +136,7 @@ fn parse_primary(tokens: &Vec<Token>, curr_token: &mut usize) -> Option<Box<dyn
Token::CHAR('(') => parse_parenthesized_exp(&tokens, curr_token),
Token::IF => parse_conditional_exp(&tokens, curr_token),
Token::FOR => parse_for_exp(&tokens, curr_token),
Token::VAR => parse_var_exp(&tokens, curr_token),
_ => {
*curr_token += 1;
None
......@@ -143,6 +144,68 @@ fn parse_primary(tokens: &Vec<Token>, curr_token: &mut usize) -> Option<Box<dyn
}
}
fn parse_var_exp(tokens: &Vec<Token>, curr_token: &mut usize) -> Option<Box<dyn Exp>> {
if let Token::VAR = &tokens[*curr_token] {
*curr_token += 1;
let mut vars = vec![];
loop {
let var;
match &tokens[*curr_token] {
Token::ID(id) => {
var = Var::new(id.clone());
*curr_token += 1;
}
_ => return None,
}
let mut assigned_var = false;
match &tokens[*curr_token] {
Token::CHAR('=') => {
*curr_token += 1;
assigned_var = true;
}
_ => (),
}
if assigned_var {
let assigned_exp = match parse_expression(&tokens, curr_token) {
Some(exp) => exp,
None => return None,
};
vars.push((var, assigned_exp));
} else {
let default_exp = Box::new(Number::new(0.0));
vars.push((var, default_exp));
}
match &tokens[*curr_token] {
Token::IN => {
break;
}
Token::CHAR(',') => {
*curr_token += 1;
continue;
}
_ => return None,
}
}
*curr_token += 1;
let body_exp = match parse_expression(&tokens, curr_token) {
Some(exp) => exp,
None => return None,
};
Some(Box::new(VarExp::new(vars, body_exp)))
} else {
None
}
}
fn parse_for_exp(tokens: &Vec<Token>, curr_token: &mut usize) -> Option<Box<dyn Exp>> {
if let Token::FOR = &tokens[*curr_token] {
*curr_token += 1;
......@@ -178,7 +241,7 @@ fn parse_for_exp(tokens: &Vec<Token>, curr_token: &mut usize) -> Option<Box<dyn
None => return None,
};
let mut step_exp : Box<dyn Exp> = Box::new(Number::new(1.0));
let mut step_exp: Box<dyn Exp> = Box::new(Number::new(1.0));
let mut default_step = false;
match &tokens[*curr_token] {
......@@ -209,7 +272,9 @@ fn parse_for_exp(tokens: &Vec<Token>, curr_token: &mut usize) -> Option<Box<dyn
None => return None,
};
Some(Box::new(ForExp::new(var, start_exp, end_exp, step_exp, body_exp)))
Some(Box::new(ForExp::new(
var, start_exp, end_exp, step_exp, body_exp,
)))
} else {
None
}
......@@ -322,6 +387,7 @@ fn parse_parenthesized_exp(tokens: &Vec<Token>, curr_token: &mut usize) -> Optio
Token::CHAR(')') => (),
_ => return None,
}
*curr_token += 1;
Some(exp)
} else {
......@@ -377,6 +443,7 @@ fn get_precedence(c: &char) -> i32 {
'+' => 20,
'-' => 20,
'*' => 40,
'=' => 0,
_ => -1,
}
}
\ No newline at end of file
}
#[cfg(test)]
pub mod tests;
\ No newline at end of file
pub mod tests;
......@@ -13,8 +13,10 @@ fn test_single_exp() {
let mu_llvm_values;
unsafe {
llvm_values = generator::code_gen(String::from("test_single_exp"), nodes.clone());
mu_values = mu_generator::code_gen(String::from("test_single_exp"), nodes.clone(), false, false);
mu_llvm_values = mu_generator::code_gen(String::from("test_single_exp"), nodes.clone(), true, false);
mu_values =
mu_generator::code_gen(String::from("test_single_exp"), nodes.clone(), false, false);
mu_llvm_values =
mu_generator::code_gen(String::from("test_single_exp"), nodes.clone(), true, false);
}
let expected: Vec<Result<f64, String>> = vec![Ok(42.0)];
......@@ -33,8 +35,18 @@ fn test_multiple_exps() {
let mu_llvm_values;
unsafe {
llvm_values = generator::code_gen(String::from("test_multiple_exps"), nodes.clone());
mu_values = mu_generator::code_gen(String::from("test_multiple_exps"), nodes.clone(), false, false);
mu_llvm_values = mu_generator::code_gen(String::from("test_multiple_exps"), nodes.clone(), true, false);
mu_values = mu_generator::code_gen(
String::from("test_multiple_exps"),
nodes.clone(),
false,
false,
);
mu_llvm_values = mu_generator::code_gen(
String::from("test_multiple_exps"),
nodes.clone(),
true,
false,
);
}
let expected: Vec<Result<f64, String>> = vec![Ok(42.0), Ok(42.0)];
......@@ -53,8 +65,18 @@ fn test_function_call() {
let mu_llvm_values;
unsafe {
llvm_values = generator::code_gen(String::from("test_function_call"), nodes.clone());
mu_values = mu_generator::code_gen(String::from("test_function_call"), nodes.clone(), false, false);
mu_llvm_values = mu_generator::code_gen(String::from("test_function_call"), nodes.clone(), true, false);
mu_values = mu_generator::code_gen(
String::from("test_function_call"),
nodes.clone(),
false,
false,
);
mu_llvm_values = mu_generator::code_gen(
String::from("test_function_call"),
nodes.clone(),
true,
false,
);
}
let expected: Vec<Result<f64, String>> = vec![Ok(6.0)];
......@@ -73,8 +95,18 @@ fn test_extern_function_call() {
let mu_llvm_values;
unsafe {
llvm_values = generator::code_gen(String::from("test_extern_function_call"), nodes.clone());
mu_values = mu_generator::code_gen(String::from("test_extern_function_call"), nodes.clone(), false, false);
mu_llvm_values = mu_generator::code_gen(String::from("test_extern_function_call"), nodes.clone(), true, false);
mu_values = mu_generator::code_gen(
String::from("test_extern_function_call"),
nodes.clone(),
false,
false,
);
mu_llvm_values = mu_generator::code_gen(
String::from("test_extern_function_call"),
nodes.clone(),
true,
false,
);
}
let expected: Vec<Result<f64, String>> = vec![Ok(0.9424888019316975)];
......@@ -93,8 +125,10 @@ fn test_simple_if() {
let mu_llvm_values;
unsafe {
llvm_values = generator::code_gen(String::from("test_simple_if"), nodes.clone());
mu_values = mu_generator::code_gen(String::from("test_simple_if"), nodes.clone(), false, false);
mu_llvm_values = mu_generator::code_gen(String::from("test_simple_if"), nodes.clone(), true, false);
mu_values =
mu_generator::code_gen(String::from("test_simple_if"), nodes.clone(), false, false);
mu_llvm_values =
mu_generator::code_gen(String::from("test_simple_if"), nodes.clone(), true, false);
}
let expected: Vec<Result<f64, String>> = vec![Ok(1.0)];
......@@ -113,8 +147,18 @@ fn test_simple_if_else_case() {
let mu_llvm_values;
unsafe {
llvm_values = generator::code_gen(String::from("test_simple_if_else_case"), nodes.clone());
mu_values = mu_generator::code_gen(String::from("test_simple_if_else_case"), nodes.clone(), false, false);
mu_llvm_values = mu_generator::code_gen(String::from("test_simple_if_else_case"), nodes.clone(), true, false);
mu_values = mu_generator::code_gen(
String::from("test_simple_if_else_case"),
nodes.clone(),
false,
false,
);
mu_llvm_values = mu_generator::code_gen(
String::from("test_simple_if_else_case"),
nodes.clone(),
true,
false,
);
}
let expected: Vec<Result<f64, String>> = vec![Ok(2.0)];
......@@ -133,8 +177,10 @@ fn test_fibonacci() {
let mu_llvm_values;
unsafe {
llvm_values = generator::code_gen(String::from("test_fibonacci"), nodes.clone());
mu_values = mu_generator::code_gen(String::from("test_fibonacci"), nodes.clone(), false, false);
mu_llvm_values = mu_generator::code_gen(String::from("test_fibonacci"), nodes.clone(), true, false);
mu_values =
mu_generator::code_gen(String::from("test_fibonacci"), nodes.clone(), false, false);
mu_llvm_values =
mu_generator::code_gen(String::from("test_fibonacci"), nodes.clone(), true, false);
}
let expected: Vec<Result<f64, String>> = vec![Ok(55.0)];
......@@ -153,12 +199,22 @@ fn test_for_loop_no_mutable() {
let mu_llvm_values;
unsafe {
llvm_values = generator::code_gen(String::from("test_for_loop_no_mutable"), nodes.clone());
mu_values = mu_generator::code_gen(String::from("test_for_loop_no_mutable"), nodes.clone(), false, false);
mu_llvm_values = mu_generator::code_gen(String::from("test_for_loop_no_mutable"), nodes.clone(), true, false);
mu_values = mu_generator::code_gen(
String::from("test_for_loop_no_mutable"),
nodes.clone(),
false,
false,
);
mu_llvm_values = mu_generator::code_gen(
String::from("test_for_loop_no_mutable"),
nodes.clone(),
true,
false,
);
}
let expected: Vec<Result<f64, String>> = vec![Ok(0.0)];
assert_eq!(llvm_values, expected);
assert_eq!(mu_values, expected);
assert_eq!(mu_llvm_values, expected);
}
\ No newline at end of file
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment