Compare commits

...

1 Commits

Author SHA1 Message Date
pca006132 814c3abf89 added array, WIP 2020-11-14 22:12:11 +08:00
3 changed files with 109 additions and 10 deletions

11
shell.nix Normal file
View File

@ -0,0 +1,11 @@
let
pkgs = import <nixpkgs> {};
in
pkgs.stdenv.mkDerivation {
name = "nac3";
buildInputs = [
pkgs.libffi
pkgs.libxml2
pkgs.llvm_8
];
}

View File

@ -223,6 +223,56 @@ impl<'ctx> CodeGen<'ctx> {
ast::ExpressionType::Number { value: ast::Number::Float { value } } => {
Ok(self.context.f64_type().const_float(*value).into())
},
ast::ExpressionType::List { elements } => {
if elements.len() == 0 {
return Err(self.compile_error(CompileErrorKind::Unsupported("Empty Array")));
}
let elements: CompileResult<Vec<_>> = elements.iter().map(|v| self.compile_expression(v)).collect();
let elements = elements?;
let ty = elements[0].get_type();
for v in elements.iter() {
if v.get_type() != ty {
return Err(self.compile_error(CompileErrorKind::IncompatibleTypes));
}
}
let len = self.context.i32_type().const_int(1 + elements.len() as u64, false);
let real_len = self.context.i32_type().const_int(elements.len() as u64, false);
let ptr = self.builder.build_array_alloca(ty, len, "tmparr");
unsafe {
let len_ptr = self.builder.build_in_bounds_gep(ptr,
&[self.context.i32_type().const_int(0, false)], "len");
self.builder.build_store(len_ptr, real_len);
}
for (i, v) in elements.iter().enumerate() {
let ptr = unsafe {
self.builder.build_in_bounds_gep(ptr,
&[self.context.i32_type().const_int(1 + i as u64, false)],
"gep")
};
self.builder.build_store(ptr, *v);
}
Ok(ptr.into())
},
ast::ExpressionType::Subscript { a, b } => {
let a = self.compile_expression(a)?;
let b = self.compile_expression(b)?;
let a = match a.get_type() {
types::BasicTypeEnum::PointerType(_) => a.into_pointer_value(),
_ => return Err(self.compile_error(CompileErrorKind::IncompatibleTypes))
};
let b = match b.get_type() {
types::BasicTypeEnum::IntType(_) => b.into_int_value().const_add(
self.context.i32_type().const_int(1, false)
),
_ => return Err(self.compile_error(CompileErrorKind::IncompatibleTypes))
};
// TODO: add range check
let ptr = unsafe {
self.builder.build_in_bounds_gep(a,
&[b], "gep")
};
Ok(self.builder.build_load(ptr, "load").into())
},
ast::ExpressionType::Identifier { name } => {
match self.namespace.get(name) {
Some(value) => Ok(self.builder.build_load(*value, name).into()),
@ -425,18 +475,47 @@ impl<'ctx> CodeGen<'ctx> {
match &statement.node {
Assign { targets, value } => {
let value = self.compile_expression(value)?;
// TODO: Handle tuple
for target in targets.iter() {
self.set_source_location(target.location);
if let ast::ExpressionType::Identifier { name } = &target.node {
let builder = &self.builder;
let target = self.namespace.entry(name.clone()).or_insert_with(
|| builder.build_alloca(value.get_type(), name));
if target.get_type() != value.get_type().ptr_type(inkwell::AddressSpace::Generic) {
return Err(self.compile_error(CompileErrorKind::IncompatibleTypes));
let value_typ = value.get_type().ptr_type(inkwell::AddressSpace::Generic);
match &target.node {
ast::ExpressionType::Identifier { name } => {
let builder = &self.builder;
let target = self.namespace.entry(name.clone()).or_insert_with(
|| builder.build_alloca(value.get_type(), name));
if target.get_type() != value_typ {
return Err(self.compile_error(CompileErrorKind::IncompatibleTypes));
}
builder.build_store(*target, value);
},
ast::ExpressionType::Subscript {a, b} => {
let a = self.compile_expression(a)?;
let b = self.compile_expression(b)?;
let a = match a.get_type() {
types::BasicTypeEnum::PointerType(_) => a.into_pointer_value(),
_ => return Err(self.compile_error(CompileErrorKind::IncompatibleTypes))
};
let b = match b.get_type() {
types::BasicTypeEnum::IntType(_) => b.into_int_value().const_add(
self.context.i32_type().const_int(1, false)
),
_ => return Err(self.compile_error(CompileErrorKind::IncompatibleTypes))
};
// TODO: range check
let target = unsafe {
self.builder.build_in_bounds_gep(a,
&[b], "gep")
};
if target.get_type() != value_typ {
return Err(self.compile_error(CompileErrorKind::IncompatibleTypes));
}
self.builder.build_store(target, value);
},
_ => {
return Err(self.compile_error(CompileErrorKind::Unsupported(
"assignment target must be an identifier")));
}
builder.build_store(*target, value);
} else {
return Err(self.compile_error(CompileErrorKind::Unsupported("assignment target must be an identifier")))
}
}
},
@ -586,7 +665,7 @@ impl<'ctx> CodeGen<'ctx> {
fn main() {
Target::initialize_all(&InitializationConfig::default());
let program = match fs::read_to_string("test.py") {
let program = match fs::read_to_string("test_arr.py") {
Ok(program) => program,
Err(err) => { println!("Cannot open input file: {}", err); return; }
};

9
test_arr.py Normal file
View File

@ -0,0 +1,9 @@
def run() -> int32:
arr = [1, 2]
output(arr[0] + arr[1])
arr2 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
arr2[output(1)][0] = 3
arr3 = [arr, arr2[0], arr2[1], arr2[2]]
output(arr3[0][0] + arr2[1][0] + arr2[2][0])
return 0