Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
ghaith committed Feb 23, 2022
1 parent cfc603f commit 50c2874
Show file tree
Hide file tree
Showing 13 changed files with 161 additions and 85 deletions.
18 changes: 3 additions & 15 deletions src/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,19 +92,7 @@ pub fn parse_built_ins(id_provider: IdProvider) -> (CompilationUnit, Vec<Diagnos
parser::parse(lexer::lex_with_ids(&src, id_provider), LinkageType::BuiltIn)
}

pub fn generate<'ink, 'b>(
builtin: &str,
generator: &'b ExpressionCodeGenerator<'ink, 'b>,
params: Vec<&AstStatement>,
source_location: SourceRange,
) -> Result<BasicValueEnum<'ink>, Diagnostic> {
BUILTIN
.get(builtin.to_uppercase().as_str())
.ok_or_else(|| {
Diagnostic::codegen_error(
&format!("Cannot find builtin function {}", builtin),
source_location.clone(),
)
})
.and_then(|it| it.codegen(generator, params.as_slice(), source_location))
/// Returns the requested functio from the builtin index or None
pub fn get_builtin(name: &str) -> Option<&'static BuiltIn> {
BUILTIN.get(name.to_uppercase().as_str())
}
12 changes: 7 additions & 5 deletions src/codegen/generators/expression_generator.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright (c) 2020 Ghaith Hachem and Mathias Rieder
use crate::{
ast::{self, DirectAccessType, SourceRange},
builtins,
codegen::llvm_typesystem,
diagnostics::{Diagnostic, INTERNAL_LLVM_ERROR},
index::{ImplementationIndexEntry, ImplementationType, Index, VariableIndexEntry},
Expand Down Expand Up @@ -451,14 +450,17 @@ impl<'a, 'b> ExpressionCodeGenerator<'a, 'b> {
})?;

//If the function is builtin, generate a basic value enum for it
if self.index.is_builtin(implementation.get_call_name()) {
return builtins::generate(
implementation.get_call_name(),
if let Some(builtin) = self
.index
.get_builtin_function(implementation.get_call_name())
{
return builtin.codegen(
self,
parameters
.as_ref()
.map(|it| ast::flatten_expression_list(it))
.unwrap_or_default(),
.unwrap_or_default()
.as_slice(),
operator.get_location(),
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
source: src/codegen/tests/code_gen_tests.rs
assertion_line: 2052
expression: result

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

@x = global i8 0
@y = global i16 0
@z = global i32 0
@red = unnamed_addr constant i32 0
@yellow = unnamed_addr constant i32 1
@green = unnamed_addr constant i32 2

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
source: src/codegen/tests/code_gen_tests.rs
assertion_line: 2076
expression: result

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

@x = global i8 0
@y = global i16 0
@z = global i32 0
@red = unnamed_addr constant i32 22
@yellow = unnamed_addr constant i32 33
@green = unnamed_addr constant i32 44

81 changes: 55 additions & 26 deletions src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ use crate::{
AstStatement, DirectAccessType, HardwareAccessType, Implementation, LinkageType, PouType,
SourceRange, TypeNature,
},
builtins,
builtins::{self, BuiltIn},
diagnostics::Diagnostic,
lexer::IdProvider,
typesystem::{self, *},
};

Expand Down Expand Up @@ -428,11 +427,6 @@ pub struct Index {
}

impl Index {
pub fn create_with_builtins(id_provider: IdProvider) -> Index {
let (unit, _) = builtins::parse_built_ins(id_provider.clone());
visitor::visit_index(Index::default(), &unit, id_provider)
}

/// imports all entries from the given index into the current index
///
/// imports all global_variables, member_variables, types and implementations
Expand All @@ -441,43 +435,40 @@ impl Index {
/// into the current one
pub fn import(&mut self, mut other: Index) {
//global variables
for (name, mut e) in other.global_variables.drain(..) {
e.initial_value =
self.maybe_import_const_expr(&mut other.constant_expressions, &e.initial_value);
for (name, e) in other.global_variables.drain(..) {
let e = self.transfer_constants(e, &mut other.constant_expressions);
self.global_variables.insert(name, e);
}

//enum_global_variables
for (name, mut e) in other.enum_global_variables.drain(..) {
e.initial_value =
self.maybe_import_const_expr(&mut other.constant_expressions, &e.initial_value);
for (name, e) in other.enum_global_variables.drain(..) {
let e = self.transfer_constants(e, &mut other.constant_expressions);
self.enum_global_variables.insert(name, e.clone());
self.enum_qualified_variables
.insert(e.qualified_name.to_lowercase(), e);
}

//initializers
for (name, mut e) in other.global_initializers.drain(..) {
e.initial_value =
self.maybe_import_const_expr(&mut other.constant_expressions, &e.initial_value);
for (name, e) in other.global_initializers.drain(..) {
let e = self.transfer_constants(e, &mut other.constant_expressions);
self.global_initializers.insert(name, e);
}

//member variables
for (name, mut members) in other.member_variables.drain(..) {
//enum qualified variables
for (_, mut e) in members.iter_mut() {
e.initial_value =
self.maybe_import_const_expr(&mut other.constant_expressions, &e.initial_value);
let mut new_members = IndexMap::default();
for (name, e) in members.drain(..) {
let e = self.transfer_constants(e, &mut other.constant_expressions);
new_members.insert(name, e);
}
self.member_variables.insert(name, members);
self.member_variables.insert(name, new_members);
}

//types
for (name, mut e) in other.type_index.types.drain(..) {
e.initial_value =
self.maybe_import_const_expr(&mut other.constant_expressions, &e.initial_value);

match &mut e.information {
//import constant expressions in array-type-definitions
DataTypeInformation::Array { dimensions, .. } => {
Expand Down Expand Up @@ -511,6 +502,38 @@ impl Index {
// self.constant_expressions.import(other.constant_expressions)
}

fn transfer_constants(
&mut self,
mut variable: VariableIndexEntry,
import_from: &mut ConstExpressions,
) -> VariableIndexEntry {
variable.initial_value = self.maybe_import_const_expr(import_from, &variable.initial_value);

let binding = if let Some(HardwareBinding {
direction,
access,
entries,
location,
}) = variable.get_hardware_binding()
{
let mut new_entries = vec![];
for entry in entries {
if let Some(e) = self.maybe_import_const_expr(import_from, &Some(*entry)) {
new_entries.push(e);
}
}
Some(HardwareBinding {
direction: *direction,
access: *access,
entries: new_entries,
location: location.clone(),
})
} else {
None
};
variable.set_hardware_binding(binding)
}

/// imports the corresponding const-expression (according to the given initializer-id) from the given ConstExpressions
/// into self's const-expressions and returns the new Id
fn maybe_import_const_expr(
Expand All @@ -520,7 +543,7 @@ impl Index {
) -> Option<ConstId> {
initializer_id
.as_ref()
.and_then(|it| import_from.remove(it))
.and_then(|it| import_from.clone(it))
.map(|(init, target_type, scope)| {
self.get_mut_const_expressions()
.add_constant_expression(init, target_type, scope)
Expand All @@ -540,7 +563,7 @@ impl Index {
let ts = match type_size {
TypeSize::LiteralInteger(_) => Some(*type_size),
TypeSize::ConstExpression(id) => import_from
.remove(id)
.clone(id)
.map(|(expr, target_type, scope)| {
self.get_mut_const_expressions().add_constant_expression(
expr,
Expand Down Expand Up @@ -970,11 +993,17 @@ impl Index {
InstanceIterator::with_filter(self, inner_filter)
}

pub fn is_builtin(&self, function: &str) -> bool {
/// If the provided name is a builtin function, returns it from the builtin index
pub fn get_builtin_function(&self, name: &str) -> Option<&'_ BuiltIn> {
//Find a type for that function, see if that type is builtin
self.find_effective_type_info(function)
if let Some(true) = self
.find_effective_type_info(name)
.map(DataTypeInformation::is_builtin)
.unwrap_or_default()
{
builtins::get_builtin(name)
} else {
None
}
}
}

Expand Down
29 changes: 22 additions & 7 deletions src/index/const_expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,29 @@ impl ConstExpressions {
self.expressions.get(*id).map(|it| &it.expr)
}

/// removes the expression from the ConstExpressions and returns all of its elements
pub fn remove(&mut self, id: &ConstId) -> Option<(AstStatement, String, Option<String>)> {
self.expressions.remove(*id).map(|it| match it.expr {
ConstExpression::Unresolved { statement, scope } => {
(statement, it.target_type_name, scope)
// /// removes the expression from the ConstExpressions and returns all of its elements
// pub fn remove(&mut self, id: &ConstId) -> Option<(AstStatement, String, Option<String>)> {
// self.expressions.remove(*id).map(|it| match it.expr {
// ConstExpression::Unresolved { statement, scope } => {
// (statement, it.target_type_name, scope)
// }
// ConstExpression::Resolved(s) => (s, it.target_type_name, None),
// ConstExpression::Unresolvable { statement: s, .. } => (s, it.target_type_name, None),
// })
// }

/// clones the expression in the ConstExpressions and returns all of its elements
pub fn clone(&self, id: &ConstId) -> Option<(AstStatement, String, Option<String>)> {
self.expressions.get(*id).map(|it| match &it.expr {
ConstExpression::Unresolved { statement, scope } => (
statement.clone(),
it.target_type_name.clone(),
scope.clone(),
),
ConstExpression::Resolved(s) => (s.clone(), it.target_type_name.clone(), None),
ConstExpression::Unresolvable { statement: s, .. } => {
(s.clone(), it.target_type_name.clone(), None)
}
ConstExpression::Resolved(s) => (s, it.target_type_name, None),
ConstExpression::Unresolvable { statement: s, .. } => (s, it.target_type_name, None),
})
}

Expand Down
9 changes: 6 additions & 3 deletions src/index/tests/builtin_tests.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
use crate::{index::Index, lexer::IdProvider, test_utils::tests::index};
use crate::{builtins, lexer::IdProvider, test_utils::tests::index};

#[test]
fn builtin_functions_added_to_index() {
let index = Index::create_with_builtins(IdProvider::default());
let provider = IdProvider::default();
let (builtins, _) = builtins::parse_built_ins(provider.clone());
let index = crate::index::visitor::visit(&builtins, provider);

assert!(index.find_member("ADR", "in").is_some());
assert!(index.find_member("REF", "in").is_some());
assert!(index.find_implementation("ADR").is_some());
assert!(index.find_implementation("REF").is_some());
}

#[test]
fn default_visitor_creates_builtins() {
fn test_indexer_has_builtins() {
let (_, index) = index("");
assert!(index.find_member("ADR", "in").is_some());
assert!(index.find_member("REF", "in").is_some());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
source: src/index/tests/instance_resolver_tests.rs
assertion_line: 169
assertion_line: 170
expression: "index.find_instances().collect::<Vec<Instance<'_>>>()"

---
Expand Down Expand Up @@ -44,7 +44,7 @@ expression: "index.find_instances().collect::<Vec<Instance<'_>>>()"
qualified_name: "MainProg.size",
initial_value: Some(
Index {
index: 2,
index: 0,
generation: 0,
},
),
Expand Down Expand Up @@ -99,13 +99,13 @@ expression: "index.find_instances().collect::<Vec<Instance<'_>>>()"
Dimension {
start_offset: ConstExpression(
Index {
index: 0,
index: 1,
generation: 0,
},
),
end_offset: ConstExpression(
Index {
index: 1,
index: 2,
generation: 0,
},
),
Expand Down Expand Up @@ -146,13 +146,13 @@ expression: "index.find_instances().collect::<Vec<Instance<'_>>>()"
Dimension {
start_offset: ConstExpression(
Index {
index: 0,
index: 1,
generation: 0,
},
),
end_offset: ConstExpression(
Index {
index: 1,
index: 2,
generation: 0,
},
),
Expand Down
9 changes: 2 additions & 7 deletions src/index/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ use crate::index::{Index, MemberInfo};
use crate::lexer::IdProvider;
use crate::typesystem::{self, *};

pub fn visit_index(mut index: Index, unit: &CompilationUnit, mut id_provider: IdProvider) -> Index {
pub fn visit(unit: &CompilationUnit, mut id_provider: IdProvider) -> Index {
let mut index = Index::default();
//Create the typesystem
let builtins = get_builtin_types();
for data_type in builtins {
Expand Down Expand Up @@ -37,12 +38,6 @@ pub fn visit_index(mut index: Index, unit: &CompilationUnit, mut id_provider: Id
index
}

/// Visits the ast, creating an index of the content. Appends builtin functions to that index
pub fn visit(unit: &CompilationUnit, id_provider: IdProvider) -> Index {
let index = Index::create_with_builtins(id_provider.clone());
visit_index(index, unit, id_provider)
}

pub fn visit_pou(index: &mut Index, pou: &Pou) {
let interface_name = format!("{}_interface", &pou.name);

Expand Down
5 changes: 5 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,8 +440,13 @@ fn parse_and_index<T: SourceContainer>(
linkage: LinkageType,
) -> Result<(Index, Units), Diagnostic> {
let mut index = Index::default();

let mut units = Vec::new();

//parse the builtins into the index
let (builtins, _) = builtins::parse_built_ins(id_provider.clone());
index.import(index::visitor::visit(&builtins, id_provider.clone()));

for container in source {
let location: String = container.get_location().into();
let e = container
Expand Down
Loading

0 comments on commit 50c2874

Please sign in to comment.