Skip to content

Commit

Permalink
Merge pull request #169 from ghaith/ast_files
Browse files Browse the repository at this point in the history
Make the AST hold a file location
  • Loading branch information
ghaith authored Apr 20, 2021
2 parents 76b1163 + 0b56ceb commit f683ab5
Show file tree
Hide file tree
Showing 27 changed files with 546 additions and 343 deletions.
93 changes: 83 additions & 10 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,45 @@ impl Variable {
}
}

pub type SourceRange = core::ops::Range<usize>;
#[derive(Clone, Debug, PartialEq)]
pub struct SourceRange {
file_path: String,
range: core::ops::Range<usize>,
}

impl SourceRange {
pub fn new(file_path: &str, range: core::ops::Range<usize>) -> SourceRange {
SourceRange {
file_path: file_path.into(),
range,
}
}

pub fn undefined() -> SourceRange {
SourceRange {
file_path: "".into(),
range: 0..0,
}
}

pub fn get_file_path(&self) -> &str {
&self.file_path
}

pub fn get_start(&self) -> usize {
self.range.start
}

pub fn get_end(&self) -> usize {
self.range.end
}
}

impl From<std::ops::Range<usize>> for SourceRange {
fn from(range: std::ops::Range<usize>) -> SourceRange {
SourceRange::new("", range)
}
}

#[derive(Clone, Debug, PartialEq)]
pub struct NewLines {
Expand Down Expand Up @@ -610,25 +648,55 @@ impl Statement {
Statement::LiteralArray { location, .. } => location.clone(),
Statement::Reference { location, .. } => location.clone(),
Statement::QualifiedReference { elements, .. } => {
elements.first().map_or(0, |it| it.get_location().start)
..elements.last().map_or(0, |it| it.get_location().end)
let first = elements
.first()
.map_or_else(SourceRange::undefined, |it| it.get_location());
let last = elements
.last()
.map_or_else(SourceRange::undefined, |it| it.get_location());
SourceRange::new(first.get_file_path(), first.get_start()..last.get_end())
}
Statement::BinaryExpression { left, right, .. } => {
left.get_location().start..right.get_location().end
let left_loc = left.get_location();
let right_loc = right.get_location();
SourceRange::new(
&left_loc.file_path,
left_loc.range.start..right_loc.range.end,
)
}
Statement::UnaryExpression { location, .. } => location.clone(),
Statement::ExpressionList { expressions } => {
expressions.first().map_or(0, |it| it.get_location().start)
..expressions.last().map_or(0, |it| it.get_location().end)
let first = expressions
.first()
.map_or_else(SourceRange::undefined, |it| it.get_location());
let last = expressions
.last()
.map_or_else(SourceRange::undefined, |it| it.get_location());
SourceRange::new(first.get_file_path(), first.get_start()..last.get_end())
}
Statement::RangeStatement { start, end } => {
start.get_location().start..end.get_location().end
let start_loc = start.get_location();
let end_loc = end.get_location();
SourceRange::new(
&start_loc.file_path,
start_loc.range.start..end_loc.range.end,
)
}
Statement::Assignment { left, right } => {
left.get_location().start..right.get_location().end
let left_loc = left.get_location();
let right_loc = right.get_location();
SourceRange::new(
&left_loc.file_path,
left_loc.range.start..right_loc.range.end,
)
}
Statement::OutputAssignment { left, right } => {
left.get_location().start..right.get_location().end
let left_loc = left.get_location();
let right_loc = right.get_location();
SourceRange::new(
&left_loc.file_path,
left_loc.range.start..right_loc.range.end,
)
}
Statement::CallStatement { location, .. } => location.clone(),
Statement::IfStatement { location, .. } => location.clone(),
Expand All @@ -637,7 +705,12 @@ impl Statement {
Statement::RepeatLoopStatement { location, .. } => location.clone(),
Statement::CaseStatement { location, .. } => location.clone(),
Statement::ArrayAccess { reference, access } => {
reference.get_location().start..access.get_location().end
let reference_loc = reference.get_location();
let access_loc = access.get_location();
SourceRange::new(
&reference_loc.file_path,
reference_loc.range.start..access_loc.range.end,
)
}
Statement::MultipliedStatement { location, .. } => location.clone(),
}
Expand Down
20 changes: 11 additions & 9 deletions src/codegen/generators/expression_generator.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) 2020 Ghaith Hachem and Mathias Rieder
use crate::index::Index;
use crate::{ast::SourceRange, index::Index};
use inkwell::{
basic_block::BasicBlock,
types::BasicTypeEnum,
Expand All @@ -9,7 +9,7 @@ use inkwell::{
},
AddressSpace, FloatPredicate, IntPredicate,
};
use std::{collections::HashSet, ops::Range};
use std::collections::HashSet;

use crate::{
ast::{flatten_expression_list, Dimension, Operator, Statement},
Expand Down Expand Up @@ -767,11 +767,13 @@ impl<'a, 'b> ExpressionCodeGenerator<'a, 'b> {
let statements = access.get_as_list();
if statements.is_empty() || statements.len() != dimensions.len() {
return Err(CompileError::codegen_error(
format!(
"Mismatched array access : {} -> {} ",
statements.len(),
dimensions.len()
),access.get_location()));
format!(
"Mismatched array access : {} -> {} ",
statements.len(),
dimensions.len()
),
access.get_location(),
));
}
for (i, statement) in statements.iter().enumerate() {
indices.push(self.generate_access_for_dimension(&dimensions[i], statement)?)
Expand Down Expand Up @@ -1109,7 +1111,7 @@ impl<'a, 'b> ExpressionCodeGenerator<'a, 'b> {
fn generate_literal_struct(
&self,
assignments: &Statement,
declaration_location: &Range<usize>,
declaration_location: &SourceRange,
) -> Result<TypeAndValue<'a>, CompileError> {
if let Some(type_info) = &self.type_hint {
if let DataTypeInformation::Struct {
Expand Down Expand Up @@ -1223,7 +1225,7 @@ impl<'a, 'b> ExpressionCodeGenerator<'a, 'b> {
fn generate_literal_array(
&self,
elements: &Option<Box<Statement>>,
location: &Range<usize>,
location: &SourceRange,
) -> Result<TypeAndValue<'a>, CompileError> {
if let Some(type_info) = &self.type_hint {
if let DataTypeInformation::Array {
Expand Down
10 changes: 8 additions & 2 deletions src/codegen/generators/llvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,10 @@ impl<'a> Llvm<'a> {

Ok((data_type, BasicValueEnum::IntValue(value.unwrap())))
} else {
Err(CompileError::codegen_error("error expected inttype".into(),0..0))
Err(CompileError::codegen_error(
"error expected inttype".into(),
SourceRange::undefined(),
))
}
}

Expand All @@ -206,7 +209,10 @@ impl<'a> Llvm<'a> {
let data_type = index.get_type_information("REAL")?;
Ok((data_type, BasicValueEnum::FloatValue(value)))
} else {
Err(CompileError::codegen_error("error expected floattype".into(),0..0))
Err(CompileError::codegen_error(
"error expected floattype".into(),
SourceRange::undefined(),
))
}
}

Expand Down
9 changes: 6 additions & 3 deletions src/codegen/generators/pou_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ impl<'ink, 'cg> PouGenerator<'ink, 'cg> {
&function_context,
&local_index,
implementation.pou_type,
Some(0..0),
None,
)?; //TODO location

Ok(())
Expand All @@ -176,7 +176,10 @@ impl<'ink, 'cg> PouGenerator<'ink, 'cg> {
Ok(enum_type.into_array_type().fn_type(params, false))
}
None => Ok(self.llvm.context.void_type().fn_type(params, false)),
_ => Err(CompileError::codegen_error(format!("Unsupported return type {:?}", return_type),0..0)),
_ => Err(CompileError::codegen_error(
format!("Unsupported return type {:?}", return_type),
SourceRange::undefined(),
)),
}
}

Expand Down Expand Up @@ -258,7 +261,7 @@ impl<'ink, 'cg> PouGenerator<'ink, 'cg> {
PouType::Function => {
let reference = Statement::Reference {
name: function_context.linking_context.get_call_name().into(),
location: location.unwrap_or(0usize..0usize),
location: location.unwrap_or_else(SourceRange::undefined),
};
let mut exp_gen = ExpressionCodeGenerator::new(
&self.llvm,
Expand Down
24 changes: 12 additions & 12 deletions src/codegen/generators/statement_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
use std::ops::Range;

use super::{expression_generator::ExpressionCodeGenerator, llvm::Llvm};
use crate::codegen::llvm_typesystem::cast_if_needed;
use crate::codegen::LlvmTypedIndex;
use crate::typesystem::{RANGE_CHECK_LS_FN, RANGE_CHECK_LU_FN, RANGE_CHECK_S_FN, RANGE_CHECK_U_FN};
use crate::{ast::SourceRange, codegen::llvm_typesystem::cast_if_needed};
use crate::{
ast::{flatten_expression_list, ConditionalBlock, Operator, Statement},
compile_error::CompileError,
Expand Down Expand Up @@ -281,10 +281,10 @@ impl<'a, 'b> StatementCodeGenerator<'a, 'b> {

/// genertes a case statement
///
/// CASE selector OF
/// conditional_block#1:
/// conditional_block#2:
/// END_CASE;
/// CASE selector OF
/// conditional_block#1:
/// conditional_block#2:
/// END_CASE;
///
/// - `selector` the case's selector expression
/// - `conditional_blocks` all case-blocks including the condition and the body
Expand Down Expand Up @@ -424,9 +424,9 @@ impl<'a, 'b> StatementCodeGenerator<'a, 'b> {

/// generates a while statement
///
/// WHILE condition DO
/// body
/// END_WHILE
/// WHILE condition DO
/// body
/// END_WHILE
///
/// - `condition` the while's condition
/// - `body` the while's body statements
Expand All @@ -452,9 +452,9 @@ impl<'a, 'b> StatementCodeGenerator<'a, 'b> {
/// generates a repeat statement
///
///
/// REPEAT
/// body
/// UNTIL condition END_REPEAT;
/// REPEAT
/// body
/// UNTIL condition END_REPEAT;
///
/// - `condition` the repeat's condition
/// - `body` the repeat's body statements
Expand Down Expand Up @@ -601,7 +601,7 @@ fn create_call_to_check_function_ast(
check_function_name: String,
parameter: Statement,
sub_range: Range<Statement>,
location: &Range<usize>,
location: &SourceRange,
) -> Statement {
Statement::CallStatement {
operator: Box::new(Statement::Reference {
Expand Down
4 changes: 2 additions & 2 deletions src/codegen/llvm_index.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) 2020 Ghaith Hachem and Mathias Rieder
use crate::compile_error::CompileError;
use crate::{ast::SourceRange, compile_error::CompileError};
use inkwell::types::BasicTypeEnum;
use inkwell::values::{BasicValueEnum, FunctionValue, GlobalValue, PointerValue};
use std::collections::HashMap;
Expand Down Expand Up @@ -99,7 +99,7 @@ impl<'ink> LlvmTypedIndex<'ink> {
type_name: &str,
) -> Result<BasicTypeEnum<'ink>, CompileError> {
self.find_associated_type(type_name)
.ok_or_else(|| CompileError::unknown_type(type_name, 0..0))
.ok_or_else(|| CompileError::unknown_type(type_name, SourceRange::undefined()))
}

pub fn find_associated_initial_value(&self, type_name: &str) -> Option<BasicValueEnum<'ink>> {
Expand Down
9 changes: 5 additions & 4 deletions src/codegen/llvm_typesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use inkwell::{
};

use crate::{
ast::SourceRange,
ast::Statement,
compile_error::CompileError,
index::Index,
Expand Down Expand Up @@ -161,13 +162,13 @@ pub fn cast_if_needed<'ctx>(
let target_type = index.find_effective_type(target_type).ok_or_else(|| {
CompileError::codegen_error(
format!("Could not find primitive type for {:?}", target_type),
0..0,
SourceRange::undefined(),
)
})?;
let value_type = index.find_effective_type(value_type).ok_or_else(|| {
CompileError::codegen_error(
format!("Could not find primitive type for {:?}", value_type),
0..0,
SourceRange::undefined(),
)
})?;
match target_type {
Expand Down Expand Up @@ -322,7 +323,7 @@ pub fn get_llvm_int_type<'a>(
128 => Ok(context.i128_type()),
_ => Err(CompileError::codegen_error(
format!("Invalid size for type : '{}' at {}", name, size),
0..0,
SourceRange::undefined(),
)),
}
}
Expand All @@ -337,7 +338,7 @@ pub fn get_llvm_float_type<'a>(
64 => Ok(context.f64_type()),
_ => Err(CompileError::codegen_error(
format!("Invalid size for type : '{}' at {}", name, size),
0..0,
SourceRange::undefined(),
)),
}
}
4 changes: 2 additions & 2 deletions src/codegen/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ mod typesystem_test;
#[macro_export]
macro_rules! codegen_wihout_unwrap {
($code:tt) => {{
let lexer = crate::lexer::lex($code);
let lexer = crate::lexer::lex("", $code);
let (mut ast, _) = crate::parser::parse(lexer).unwrap();

let context = inkwell::context::Context::create();
Expand All @@ -20,7 +20,7 @@ macro_rules! codegen_wihout_unwrap {
#[macro_export]
macro_rules! codegen {
($code:tt) => {{
let lexer = crate::lexer::lex($code);
let lexer = crate::lexer::lex("", $code);
let (mut ast, _) = crate::parser::parse(lexer).unwrap();

let context = inkwell::context::Context::create();
Expand Down
2 changes: 1 addition & 1 deletion src/codegen/tests/code_gen_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3939,7 +3939,7 @@ fn struct_initializer_needs_assignments() {
Err(CompileError::codegen_error(
"struct literal must consist of explicit assignments in the form of member := value"
.to_string(),
185..186
(185..186).into()
))
);
assert_eq!(source[185..186].to_string(), "2".to_string());
Expand Down
Loading

0 comments on commit f683ab5

Please sign in to comment.