Skip to content

Commit

Permalink
Merge pull request #84 from lambdaclass/parse_floats_chars_string_une…
Browse files Browse the repository at this point in the history
…scape

Parse floats, parse chars and strings with escape codes
  • Loading branch information
unbalancedparentheses authored Feb 6, 2024
2 parents e8671e5 + d207c3a commit 53843d8
Show file tree
Hide file tree
Showing 11 changed files with 188 additions and 93 deletions.
44 changes: 44 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions crates/concrete_ast/src/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ pub enum Expression {
pub enum ValueExpr {
ConstBool(bool),
ConstChar(char),
ConstInt(u64),
ConstFloat(()),
ConstInt(u128),
ConstFloat(String),
ConstStr(String),
Path(PathOp),
Deref(PathOp),
Expand Down
23 changes: 21 additions & 2 deletions crates/concrete_codegen_mlir/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ use melior::{
cf, func, memref,
},
ir::{
attribute::{FlatSymbolRefAttribute, IntegerAttribute, StringAttribute, TypeAttribute},
attribute::{
FlatSymbolRefAttribute, FloatAttribute, IntegerAttribute, StringAttribute,
TypeAttribute,
},
r#type::{FunctionType, IntegerType, MemRefType},
Block, BlockRef, Location, Module as MeliorModule, Operation, Region, Type, Value,
ValueLike,
Expand Down Expand Up @@ -132,6 +135,7 @@ impl<'ctx, 'parent> ScopeContext<'ctx, 'parent> {
"u32" | "i32" => IntegerType::new(context, 32).into(),
"u16" | "i16" => IntegerType::new(context, 16).into(),
"u8" | "i8" => IntegerType::new(context, 8).into(),
"char" => IntegerType::new(context, 32).into(),
"f32" => Type::float32(context),
"f64" => Type::float64(context),
"bool" => IntegerType::new(context, 1).into(),
Expand Down Expand Up @@ -828,7 +832,22 @@ fn compile_value_expr<'ctx, 'parent: 'ctx>(
.result(0)?
.into())
}
ValueExpr::ConstFloat(_) => todo!(),
ValueExpr::ConstFloat(value) => {
let float_type = if let Some(type_info) = type_info {
scope_ctx.resolve_type_spec(context, type_info)?
} else {
Type::float64(context)
};
let value = FloatAttribute::new(
context,
value.parse().expect("failed to parse float"),
float_type,
);
Ok(block
.append_operation(arith::constant(context, value.into(), location))
.result(0)?
.into())
}
ValueExpr::ConstStr(_) => todo!(),
ValueExpr::Path(value) => {
compile_path_op(session, context, scope_ctx, _helper, block, value)
Expand Down
1 change: 1 addition & 0 deletions crates/concrete_driver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ concrete_check = { version = "0.1.0", path = "../concrete_check" }

[dev-dependencies]
tempfile = "3.9.0"
test-case = "3.3.1"
87 changes: 17 additions & 70 deletions crates/concrete_driver/tests/examples.rs
Original file line number Diff line number Diff line change
@@ -1,77 +1,24 @@
use crate::common::{compile_program, run_program};
use test_case::test_case;

mod common;

#[test]
fn borrow() {
let program = compile_program(
include_str!("../../../examples/borrow.con"),
"borrow",
false,
)
.unwrap();
#[test_case(include_str!("../../../examples/borrow.con"), "borrow", false, 2 ; "borrow.con")]
#[test_case(include_str!("../../../examples/factorial_if.con"), "factorial_if", false, 24 ; "factorial_if.con")]
#[test_case(include_str!("../../../examples/fib_if.con"), "fib_if", false, 55 ; "fib_if.con")]
#[test_case(include_str!("../../../examples/import.con"), "import", false, 12 ; "import.con")]
#[test_case(include_str!("../../../examples/simple.con"), "simple", false, 8 ; "simple.con")]
#[test_case(include_str!("../../../examples/while.con"), "while", false, 16 ; "while.con")]
#[test_case(include_str!("../../../examples/chars.con"), "chars", false, 117 ; "chars.con")]
#[test_case(include_str!("../../../examples/floats.con"), "floats", false, 1 ; "floats.con")]
fn example_tests(source: &str, name: &str, is_library: bool, status_code: i32) {
let program = compile_program(source, name, is_library).unwrap();

let result = run_program(&program.binary_file).unwrap();
assert_eq!(result.status.code().unwrap(), 2);
}

#[test]
fn factorial_if() {
let program = compile_program(
include_str!("../../../examples/factorial_if.con"),
"factorial_if",
false,
)
.unwrap();

let result = run_program(&program.binary_file).unwrap();
assert_eq!(result.status.code().unwrap(), 24);
}

#[test]
fn fib_if() {
let program = compile_program(
include_str!("../../../examples/fib_if.con"),
"fib_if",
false,
)
.unwrap();

let result = run_program(&program.binary_file).unwrap();
assert_eq!(result.status.code().unwrap(), 55);
}

#[test]
fn import() {
let program = compile_program(
include_str!("../../../examples/import.con"),
"import",
false,
)
.unwrap();

let result = run_program(&program.binary_file).unwrap();
assert_eq!(result.status.code().unwrap(), 12);
}

#[test]
fn simple() {
let program = compile_program(
include_str!("../../../examples/simple.con"),
"simple",
false,
)
.unwrap();

let result = run_program(&program.binary_file).unwrap();
assert_eq!(result.status.code().unwrap(), 8);
}

#[test]
fn r#while() {
let program =
compile_program(include_str!("../../../examples/while.con"), "while", false).unwrap();

let result = run_program(&program.binary_file).unwrap();
assert_eq!(result.status.code().unwrap(), 16);
assert_eq!(
result.status.code().unwrap(),
status_code,
"Program {} returned a unexpected status code",
name
);
}
60 changes: 46 additions & 14 deletions crates/concrete_driver/tests/programs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,26 +132,58 @@ fn test_import() {
}

#[test]
fn test_reference() {
fn test_floats() {
let source = r#"
mod Simple {
fn main(argc: i64) -> i64 {
let x: i64 = argc;
return references(x) + dereference(&x);
}
mod Simple {
fn main() -> i64 {
let a: f32 = my_f32(2.0, 4.0);
let b: f64 = my_f64(2.0, 4.0);
return 1;
}
fn dereference(a: &i64) -> i64 {
return *a;
}
fn my_f32(x: f32, y: f32) -> f32 {
let literal: f32 = 2.0;
let literal2: f32 = 2.001;
let literal3: f32 = 0.1;
return x + y + literal2 + literal3;
}
fn references(a: i64) -> i64 {
let x: i64 = a;
let y: &i64 = &x;
return *y;
}
fn my_f64(x: f64, y: f64) -> f64 {
let literal: f64 = 2.0;
let literal2: f64 = 2.002;
let literal3: f64 = 0.02;
return x + y + literal2 + literal3;
}
}
"#;

let result = compile_program(source, "floats", false).expect("failed to compile");

let output = run_program(&result.binary_file).expect("failed to run");
let code = output.status.code().unwrap();
assert_eq!(code, 1);
}

#[test]
fn test_reference() {
let source = r#"
mod Simple {
fn main(argc: i64) -> i64 {
let x: i64 = argc;
return references(x) + dereference(&x);
}
fn dereference(a: &i64) -> i64 {
return *a;
}
fn references(a: i64) -> i64 {
let x: i64 = a;
let y: &i64 = &x;
return *y;
}
}
"#;
let result = compile_program(source, "references", false).expect("failed to compile");

let output = run_program(&result.binary_file).expect("failed to run");
Expand Down
1 change: 1 addition & 0 deletions crates/concrete_parser/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ concrete_ast = { path = "../concrete_ast"}
salsa = { git = "https://github.com/salsa-rs/salsa.git", package = "salsa-2022" }
ariadne = { version = "0.4.0", features = ["auto-color"] }
itertools = "0.12.0"
unescaper = "0.1.3"

[build-dependencies]
lalrpop = "0.20.0"
8 changes: 6 additions & 2 deletions crates/concrete_parser/src/grammar.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ extern {

// literals
"identifier" => Token::Identifier(<String>),
"integer" => Token::Integer(<u64>),
"integer" => Token::Integer(<u128>),
"float" => Token::Float(<String>),
"string" => Token::String(<String>),
"char" => Token::Char(<char>),
"boolean" => Token::Boolean(<bool>),

// Other
Expand Down Expand Up @@ -150,7 +152,7 @@ pub(crate) TypeSpec: ast::types::TypeSpec = {
},
<lo:@L> <is_ref:RefType?> "[" <of_type:TypeSpec> <size:(";" <"integer">)?> "]"<hi:@R> => ast::types::TypeSpec::Array {
of_type: Box::new(of_type),
size,
size: size.map(|x| x.try_into().expect("size is too big")),
is_ref,
span: Span::new(lo, hi),
}
Expand Down Expand Up @@ -358,8 +360,10 @@ pub UnaryOp: ast::expressions::UnaryOp = {

pub(crate) ValueExpr: ast::expressions::ValueExpr = {
<"integer"> => ast::expressions::ValueExpr::ConstInt(<>),
<"float"> => ast::expressions::ValueExpr::ConstFloat(<>),
<"boolean"> => ast::expressions::ValueExpr::ConstBool(<>),
<"string"> => ast::expressions::ValueExpr::ConstStr(<>),
<"char"> => ast::expressions::ValueExpr::ConstChar(<>),
<PathOp> => ast::expressions::ValueExpr::Path(<>),
"*" <PathOp> => ast::expressions::ValueExpr::Deref(<>),
<ref_type:RefType> <path:PathOp> => ast::expressions::ValueExpr::AsRef {
Expand Down
19 changes: 16 additions & 3 deletions crates/concrete_parser/src/tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,25 @@ pub enum Token {
Identifier(String),

// Literals
#[regex(r"\d+", |lex| lex.slice().parse::<u64>().unwrap())]
Integer(u64),
#[regex(r#""(?:[^"]|\\")*""#, |lex| lex.slice().to_string())]
#[regex(r"\d+", |lex| lex.slice().parse::<u128>().unwrap(), priority = 2)]
Integer(u128),
#[regex(r"\d+\.\d+", |lex| lex.slice().to_string(), priority = 1)]
Float(String),
#[regex(r#""(?:[^"]|\\")*""#, |lex| {
let slice = lex.slice();
let len = slice.len();
unescaper::unescape(&slice[1..(len-1)]).expect("failed to unescape string")
})]
String(String),
#[regex(r"(true|false)", |lex| lex.slice().parse::<bool>().unwrap())]
Boolean(bool),
#[regex(r#"'(?:[^']|\\')*'"#, |lex| {
let slice = lex.slice();
let len = slice.len();
let real_char = unescaper::unescape(&slice[1..(len-1)]).expect("failed to unescape char").to_string();
real_char.chars().next().unwrap()
})]
Char(char),

#[token("(")]
LeftParen,
Expand Down
13 changes: 13 additions & 0 deletions examples/chars.con
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
mod Simple {
fn main() -> char {
let a: char = hello_chars('\t');
return a;
}

fn hello_chars(a: char) -> char {
let x: char = 'b';
let newline: char = '\n';

return x + newline + a;
}
}
Loading

0 comments on commit 53843d8

Please sign in to comment.