Skip to content

Commit

Permalink
Merge branch 'master' into issue-353-Pointer-Arithmetic_assigning_a_p…
Browse files Browse the repository at this point in the history
…ointer_s_address_to_a_DWORD
  • Loading branch information
ghaith authored Dec 3, 2021
2 parents abd9451 + 8407135 commit 190899e
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 2 deletions.
13 changes: 11 additions & 2 deletions src/codegen/generators/expression_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1300,9 +1300,18 @@ impl<'a, 'b> ExpressionCodeGenerator<'a, 'b> {
self.generate_literal_array(literal_statement)
}
AstStatement::LiteralNull { .. } => self.llvm.create_null_ptr(),
// if there is an expression-list this might be a struct-initialization
// if there is an expression-list this might be a struct-initialization or array-initialization
AstStatement::ExpressionList { .. } => {
self.generate_literal_struct(literal_statement, &literal_statement.get_location())
let type_hint = self.get_type_hint_info_for(literal_statement)?;
match type_hint {
DataTypeInformation::Array { .. } => {
self.generate_literal_array(literal_statement)
}
_ => self.generate_literal_struct(
literal_statement,
&literal_statement.get_location(),
),
}
}
// if there is just one assignment, this may be an struct-initialization (TODO this is not very elegant :-/ )
AstStatement::Assignment { .. } => {
Expand Down
15 changes: 15 additions & 0 deletions src/codegen/tests/code_gen_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5757,3 +5757,18 @@ fn variable_with_same_name_as_function() {
);
insta::assert_snapshot!(result);
}

#[test]
fn expression_list_as_array_initilization() {
let result = codegen(
"
VAR_GLOBAL
arr : ARRAY[0..3] OF INT := 1, 2, 3;
b_exp : ARRAY[0..4] OF DINT := 1+3, 2*3, 7-1, 10;
str : ARRAY[0..2] OF STRING := 'first', 'second';
END_VAR
",
);

insta::assert_snapshot!(result);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
source: src/codegen/tests/code_gen_tests.rs
expression: result

---
; ModuleID = 'main'
source_filename = "main"

@arr = global [4 x i16] [i16 1, i16 2, i16 3]
@b_exp = global [5 x i32] [i32 4, i32 6, i32 6, i32 10]
@str = global [3 x [81 x i8]] [[81 x i8] c"first\00", [81 x i8] c"second\00"]

23 changes: 23 additions & 0 deletions src/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,29 @@ impl<'i> TypeAnnotator<'i> {
statement,
StatementAnnotation::value(expected_type.get_name()),
)
} else if let DataTypeInformation::Array {
inner_type_name, ..
} = expected_type.get_type_information()
{
self.annotation_map
.annotate_type_hint(statement, StatementAnnotation::value(inner_type_name))
} else {
//annotate the statement, whatever it is
self.annotation_map.annotate_type_hint(
statement,
StatementAnnotation::value(expected_type.get_name()),
)
}
}
AstStatement::LiteralString { .. } | AstStatement::BinaryExpression { .. } => {
// needed if we try to initialize an array with an expression-list
// without we would annotate a false type this would leed to an error in expression_generator
if let DataTypeInformation::Array {
inner_type_name, ..
} = expected_type.get_type_information()
{
self.annotation_map
.annotate_type_hint(statement, StatementAnnotation::value(inner_type_name))
} else {
//annotate the statement, whatever it is
self.annotation_map.annotate_type_hint(
Expand Down
17 changes: 17 additions & 0 deletions src/resolver/const_evaluator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ fn needs_evaluation(expr: &AstStatement) -> bool {
}
_ => needs_evaluation(elements.as_ref()),
},
AstStatement::ExpressionList { expressions, .. } => {
expressions.iter().any(|it| needs_evaluation(it))
}
_ => true,
}
}
Expand Down Expand Up @@ -522,6 +525,20 @@ pub fn evaluate(
location: location.clone(),
})
}
AstStatement::ExpressionList { expressions, id } => {
let inner_elements = expressions
.iter()
.map(|e| evaluate(e, scope, index))
.collect::<Result<Vec<Option<AstStatement>>, String>>()?
.into_iter()
.collect::<Option<Vec<AstStatement>>>();

//return a new array, or return none if one was not resolvable
inner_elements.map(|ie| AstStatement::ExpressionList {
expressions: ie,
id: *id,
})
}
AstStatement::MultipliedStatement {
element,
id,
Expand Down
60 changes: 60 additions & 0 deletions src/resolver/tests/resolve_literals_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,3 +418,63 @@ fn array_initialization_is_annotated_correctly() {
t.get_name()
)
}

#[test]
fn expression_list_as_array_initilization_is_annotated_correctly() {
// GIVEN two global variables beeing initialized with expression lists
let (unit, index) = index(
"
VAR_GLOBAL
a : ARRAY[0..2] OF INT := 1+1,2;
b : ARRAY[0..2] OF STRING := 'ABC','DEF';
END_VAR
",
);

// WHEN annotation is done
let annotations = annotate(&unit, &index);

// THEN for the first statement
let a_init = unit.global_vars[0].variables[0]
.initializer
.as_ref()
.unwrap();
// all expressions should be annotated with the right type [INT]
if let AstStatement::ExpressionList { expressions, .. } = a_init {
for exp in expressions {
if let Some(data_type) = annotations.get_type_hint(exp, &index) {
let type_info = data_type.get_type_information();
assert_eq!(
true,
matches!(type_info, DataTypeInformation::Integer { .. })
)
} else {
unreachable!();
}
}
} else {
unreachable!();
}

// AND for the second statement
let b_init = unit.global_vars[0].variables[1]
.initializer
.as_ref()
.unwrap();
// all expressions should be annotated with the right type [STRING]
if let AstStatement::ExpressionList { expressions, .. } = b_init {
for exp in expressions {
if let Some(data_type) = annotations.get_type_hint(exp, &index) {
let type_info = data_type.get_type_information();
assert_eq!(
true,
matches!(type_info, DataTypeInformation::String { .. })
)
} else {
unreachable!();
}
}
} else {
unreachable!();
}
}

0 comments on commit 190899e

Please sign in to comment.