Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/codegen/generators/data_type_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,8 @@ fn register_aliased_initial_value<'ink>(
} else {
// if there's no initializer defined for this alias, we go and check the aliased type for an initial value
index
.get_types()
.get(referenced_type)
.get_type(referenced_type)
.ok()
.and_then(|referenced_data_type| {
generate_initial_value(index, types_index, llvm, referenced_data_type)
})
Expand Down
32 changes: 18 additions & 14 deletions src/codegen/llvm_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ impl<'ink> LlvmTypedIndex<'ink> {
type_name: &str,
target_type: BasicTypeEnum<'ink>,
) -> Result<(), CompileError> {
self.type_associations.insert(type_name.into(), target_type);
self.type_associations
.insert(type_name.to_lowercase(), target_type);
Ok(())
}

Expand All @@ -70,7 +71,7 @@ impl<'ink> LlvmTypedIndex<'ink> {
initial_value: BasicValueEnum<'ink>,
) -> Result<(), CompileError> {
self.initial_value_associations
.insert(type_name.into(), initial_value);
.insert(type_name.to_lowercase(), initial_value);
Ok(())
}

Expand All @@ -82,16 +83,19 @@ impl<'ink> LlvmTypedIndex<'ink> {
) -> Result<(), CompileError> {
let qualified_name = format!("{}.{}", container_name, variable_name);
self.loaded_variable_associations
.insert(qualified_name, target_value);
.insert(qualified_name.to_lowercase(), target_value);
Ok(())
}

pub fn find_associated_type(&self, type_name: &str) -> Option<BasicTypeEnum<'ink>> {
self.type_associations.get(type_name).copied().or_else(|| {
self.parent_index
.map(|it| it.find_associated_type(type_name))
.flatten()
})
self.type_associations
.get(&type_name.to_lowercase())
.copied()
.or_else(|| {
self.parent_index
.map(|it| it.find_associated_type(type_name))
.flatten()
})
}

pub fn get_associated_type(
Expand All @@ -104,7 +108,7 @@ impl<'ink> LlvmTypedIndex<'ink> {

pub fn find_associated_initial_value(&self, type_name: &str) -> Option<BasicValueEnum<'ink>> {
self.initial_value_associations
.get(type_name)
.get(&type_name.to_lowercase())
.copied()
.or_else(|| {
self.parent_index
Expand All @@ -119,7 +123,7 @@ impl<'ink> LlvmTypedIndex<'ink> {
global_variable: GlobalValue<'ink>,
) -> Result<(), CompileError> {
self.initial_value_associations.insert(
variable_name.into(),
variable_name.to_lowercase(),
global_variable.as_pointer_value().into(),
);
Ok(())
Expand All @@ -131,7 +135,7 @@ impl<'ink> LlvmTypedIndex<'ink> {
function_value: FunctionValue<'ink>,
) -> Result<(), CompileError> {
self.implementations
.insert(callable_name.into(), function_value);
.insert(callable_name.to_lowercase(), function_value);
Ok(())
}

Expand All @@ -140,7 +144,7 @@ impl<'ink> LlvmTypedIndex<'ink> {
callable_name: &str,
) -> Option<FunctionValue<'ink>> {
self.implementations
.get(callable_name)
.get(&callable_name.to_lowercase())
.copied()
.or_else(|| {
self.parent_index
Expand All @@ -154,7 +158,7 @@ impl<'ink> LlvmTypedIndex<'ink> {
qualified_name: &str,
) -> Option<BasicValueEnum<'ink>> {
self.initial_value_associations
.get(qualified_name)
.get(&qualified_name.to_lowercase())
.copied()
.or_else(|| {
self.parent_index
Expand All @@ -169,7 +173,7 @@ impl<'ink> LlvmTypedIndex<'ink> {
) -> Option<PointerValue<'ink>> {
let result = self
.loaded_variable_associations
.get(qualified_name)
.get(&qualified_name.to_lowercase())
.copied()
.or_else(|| {
self.parent_index
Expand Down
37 changes: 37 additions & 0 deletions src/codegen/tests/code_gen_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ entry:

assert_eq!(result, expected);
}

#[test]
fn program_with_variables_generates_void_function_and_struct() {
let result = codegen!(
Expand Down Expand Up @@ -580,6 +581,42 @@ entry:
assert_eq!(result, expected);
}

#[test]
fn different_case_references() {
let result = codegen!(
r#"
TYPE MyInt: INT := 1; END_TYPE
TYPE MyDInt: DINT := 2; END_TYPE

PROGRAM prg
VAR
y : int;
z : MyInt;
zz : Mydint;
END_VAR
END_PROGRAM
"#
);

let expected = r#"; ModuleID = 'main'
source_filename = "main"

%prg_interface = type { i16, i16, i32 }

@prg_instance = global %prg_interface { i16 0, i32 1, i32 2 }

define void @prg(%prg_interface* %0) {
entry:
%y = getelementptr inbounds %prg_interface, %prg_interface* %0, i32 0, i32 0
%z = getelementptr inbounds %prg_interface, %prg_interface* %0, i32 0, i32 1
%zz = getelementptr inbounds %prg_interface, %prg_interface* %0, i32 0, i32 2
ret void
}
"#;

assert_eq!(result, expected);
}

#[test]
fn program_with_string_type_assignment() {
let result = codegen!(
Expand Down
42 changes: 23 additions & 19 deletions src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,26 +193,26 @@ impl Index {
}

pub fn find_global_variable(&self, name: &str) -> Option<&VariableIndexEntry> {
self.global_variables.get(name)
self.global_variables.get(&name.to_lowercase())
}

pub fn find_member(&self, pou_name: &str, variable_name: &str) -> Option<&VariableIndexEntry> {
self.member_variables
.get(pou_name)
.and_then(|map| map.get(variable_name))
.get(&pou_name.to_lowercase())
.and_then(|map| map.get(&variable_name.to_lowercase()))
}

pub fn find_local_members(&self, container_name: &str) -> Vec<&VariableIndexEntry> {
self.member_variables
.get(container_name)
.get(&container_name.to_lowercase())
.map(|it| it.values().collect())
.unwrap_or_else(Vec::new)
}

/// Returns true if the current index is a VAR_INPUT, VAR_IN_OUT or VAR_OUTPUT that is not a variadic argument
pub fn is_declared_parameter(&self, pou_name: &str, index: u32) -> bool {
self.member_variables
.get(pou_name)
.get(&pou_name.to_lowercase())
.and_then(|map| {
map.values()
.filter(|item| {
Expand All @@ -226,11 +226,13 @@ impl Index {
}

pub fn find_input_parameter(&self, pou_name: &str, index: u32) -> Option<&VariableIndexEntry> {
self.member_variables.get(pou_name).and_then(|map| {
map.values()
.filter(|item| item.information.variable_type == VariableType::Input)
.find(|item| item.information.location == index)
})
self.member_variables
.get(&pou_name.to_lowercase())
.and_then(|map| {
map.values()
.filter(|item| item.information.variable_type == VariableType::Input)
.find(|item| item.information.location == index)
})
}

pub fn find_variable(
Expand Down Expand Up @@ -260,7 +262,7 @@ impl Index {
}

pub fn find_type(&self, type_name: &str) -> Option<&DataType> {
self.types.get(type_name)
self.types.get(&type_name.to_lowercase())
}

pub fn find_effective_type_by_name(&self, type_name: &str) -> Option<&DataType> {
Expand Down Expand Up @@ -322,7 +324,7 @@ impl Index {
}

pub fn find_return_variable(&self, pou_name: &str) -> Option<&VariableIndexEntry> {
let members = self.member_variables.get(pou_name); //.ok_or_else(||CompileError::unknown_type(pou_name, 0..0))?;
let members = self.member_variables.get(&pou_name.to_lowercase()); //.ok_or_else(||CompileError::unknown_type(pou_name, 0..0))?;
if let Some(members) = members {
for (_, variable) in members {
if variable.information.variable_type == VariableType::Return {
Expand Down Expand Up @@ -351,7 +353,8 @@ impl Index {
.ok_or_else(|| CompileError::unknown_type(type_name, SourceRange::undefined()))
}

pub fn get_types(&self) -> &IndexMap<String, DataType> {
/// Returns a list of types, should not be used to search for types, just to react on them
pub(crate) fn get_types(&self) -> &IndexMap<String, DataType> {
&self.types
}

Expand All @@ -370,7 +373,7 @@ impl Index {
impl_type: ImplementationType,
) {
self.implementations.insert(
call_name.into(),
call_name.to_lowercase(),
ImplementationIndexEntry {
call_name: call_name.into(),
type_name: type_name.into(),
Expand All @@ -380,7 +383,7 @@ impl Index {
}

pub fn find_implementation(&self, call_name: &str) -> Option<&ImplementationIndexEntry> {
self.implementations.get(call_name)
self.implementations.get(&call_name.to_lowercase())
}

/// registers a member-variable of a container to be accessed in a qualified name.
Expand All @@ -407,7 +410,7 @@ impl Index {

let members = self
.member_variables
.entry(container_name.into())
.entry(container_name.to_lowercase())
.or_insert_with(IndexMap::new);

let qualified_name = format!("{}.{}", container_name, variable_name);
Expand All @@ -424,7 +427,7 @@ impl Index {
location,
},
};
members.insert(variable_name.into(), entry);
members.insert(variable_name.to_lowercase(), entry);
}

pub fn register_global_variable(
Expand Down Expand Up @@ -466,7 +469,8 @@ impl Index {
location: 0,
},
};
self.global_variables.insert(association_name.into(), entry);
self.global_variables
.insert(association_name.to_lowercase(), entry);
}

pub fn print_global_variables(&self) {
Expand All @@ -484,7 +488,7 @@ impl Index {
initial_value,
information,
};
self.types.insert(type_name.into(), index_entry);
self.types.insert(type_name.to_lowercase(), index_entry);
}

pub fn find_callable_instance_variable(
Expand Down
45 changes: 43 additions & 2 deletions src/index/tests/index_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,47 @@ fn lex(source: &str) -> lexer::ParseSession {
lexer::lex(source)
}

#[test]
fn index_not_case_sensitive() {
let index = index!(
r#"
TYPE st : STRUCT
x : INT;
y : DINT;
END_STRUCT
END_TYPE

VAR_GLOBAL
a: INT;
x : ST;
END_VAR
FUNCTION foo : INT
END_FUNCTION

PROGRAM aProgram
VAR
c,d : INT;
END_VAR
END_PROGRAM
"#
);

let entry = index.find_global_variable("A").unwrap();
assert_eq!("a", entry.name);
assert_eq!("INT", entry.information.data_type_name);
let entry = index.find_global_variable("X").unwrap();
assert_eq!("x", entry.name);
assert_eq!("ST", entry.information.data_type_name);
let entry = index.find_member("ST", "X").unwrap();
assert_eq!("x", entry.name);
assert_eq!("INT", entry.information.data_type_name);
let entry = index.find_type("APROGRAM").unwrap();
assert_eq!("aProgram", entry.name);
let entry = index.find_implementation("Foo").unwrap();
assert_eq!("foo", entry.call_name);
assert_eq!("foo", entry.type_name);
}

#[test]
fn global_variables_are_indexed() {
let index = index!(
Expand Down Expand Up @@ -1152,7 +1193,7 @@ fn sub_range_boundaries_are_registered_at_the_index() {
let index = index!(src);

// THEN I expect the index to contain the defined range-information for the given type
let my_int = &index.get_types().get("MyInt").unwrap().information;
let my_int = &index.get_type("MyInt").unwrap().information;
let expected = &DataTypeInformation::SubRange {
name: "MyInt".to_string(),
referenced_type: "INT".to_string(),
Expand All @@ -1170,7 +1211,7 @@ fn sub_range_boundaries_are_registered_at_the_index() {
assert_eq!(format!("{:?}", expected), format!("{:?}", my_int));

// THEN I expect the index to contain the defined range-information for the given type
let my_int = &index.get_types().get("MyAliasInt").unwrap().information;
let my_int = &index.get_type("MyAliasInt").unwrap().information;
let expected = &DataTypeInformation::Alias {
name: "MyAliasInt".to_string(),
referenced_type: "MyInt".to_string(),
Expand Down
4 changes: 3 additions & 1 deletion src/index/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ pub fn visit(unit: &CompilationUnit) -> Index {
//Create the typesystem
let builtins = get_builtin_types();
for data_type in builtins {
index.types.insert(data_type.get_name().into(), data_type);
index
.types
.insert(data_type.get_name().to_lowercase(), data_type);
}

//Create user defined datatypes
Expand Down
2 changes: 2 additions & 0 deletions src/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ impl<'a> ParseSession<'a> {
| Token::KeywordVarOutput
| Token::KeywordVarGlobal
| Token::KeywordVarInOut
| Token::KeywordVarTemp
| Token::KeywordNonRetain
| Token::KeywordEndVar
| Token::KeywordEndProgram
| Token::KeywordEndFunction
Expand Down
Loading