mirror of
https://github.com/exoticorn/curlywas.git
synced 2026-01-20 19:56:42 +01:00
Compare commits
2 Commits
1e746be750
...
01d64baaab
| Author | SHA1 | Date | |
|---|---|---|---|
| 01d64baaab | |||
| a52fe53a01 |
13
src/emit.rs
13
src/emit.rs
@@ -289,7 +289,7 @@ struct FunctionContext<'a> {
|
||||
functions: &'a HashMap<String, u32>,
|
||||
locals: &'a ast::Locals,
|
||||
labels: Vec<String>,
|
||||
let_values: HashMap<u32, (&'a ast::Expression, ast::LetType)>,
|
||||
let_values: HashMap<u32, Vec<(&'a ast::Expression, ast::LetType)>>,
|
||||
intrinsics: &'a Intrinsics,
|
||||
}
|
||||
|
||||
@@ -385,7 +385,10 @@ fn emit_expression<'a>(ctx: &mut FunctionContext<'a>, expr: &'a ast::Expression)
|
||||
.instruction(&Instruction::LocalSet(local.index.unwrap()));
|
||||
}
|
||||
ast::LetType::Lazy | ast::LetType::Inline => {
|
||||
ctx.let_values.insert(local_id.unwrap(), (value, *let_type));
|
||||
ctx.let_values
|
||||
.entry(local_id.unwrap())
|
||||
.or_default()
|
||||
.push((value, *let_type));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -612,17 +615,17 @@ fn emit_expression<'a>(ctx: &mut FunctionContext<'a>, expr: &'a ast::Expression)
|
||||
}
|
||||
ast::Expr::Variable { name, local_id } => {
|
||||
if let &Some(id) = local_id {
|
||||
if let Some((expr, let_type)) = ctx.let_values.get(&id) {
|
||||
if let Some((expr, let_type)) = ctx.let_values.get_mut(&id).and_then(|s| s.pop()) {
|
||||
match let_type {
|
||||
ast::LetType::Lazy => {
|
||||
let expr = ctx.let_values.remove(&id).unwrap().0;
|
||||
emit_expression(ctx, expr);
|
||||
ctx.let_values.get_mut(&id).unwrap().clear();
|
||||
ctx.function
|
||||
.instruction(&Instruction::LocalTee(ctx.locals[id].index.unwrap()));
|
||||
}
|
||||
ast::LetType::Inline => {
|
||||
let expr = *expr;
|
||||
emit_expression(ctx, expr);
|
||||
ctx.let_values.get_mut(&id).unwrap().push((expr, let_type));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
123
src/parser.rs
123
src/parser.rs
@@ -318,13 +318,27 @@ fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = LexerError> {
|
||||
Token::Int(value as i32)
|
||||
});
|
||||
|
||||
let op = one_of("+-*/%&^|<=>#")
|
||||
.repeated()
|
||||
.at_least(1)
|
||||
.or(just(':').chain(just('=')))
|
||||
.or(just('!').chain(just('=')))
|
||||
.collect::<String>()
|
||||
.map(Token::Op);
|
||||
let op = choice((
|
||||
just("#/"),
|
||||
just("#%"),
|
||||
just("<<"),
|
||||
just(">>"),
|
||||
just("#>>"),
|
||||
just("#<"),
|
||||
just("#>"),
|
||||
just(">="),
|
||||
just("<="),
|
||||
just("=="),
|
||||
just("!="),
|
||||
just("#>="),
|
||||
just("#<="),
|
||||
just("->"),
|
||||
just(":="),
|
||||
))
|
||||
.map(|s| s.to_string())
|
||||
.or(one_of("+-*/%&^|<=>").map(|s: char| s.to_string()))
|
||||
.map(Token::Op)
|
||||
.boxed();
|
||||
|
||||
let ctrl = one_of("(){};,:?!$").map(Token::Ctrl);
|
||||
|
||||
@@ -412,7 +426,7 @@ fn parse_string_escapes(s: String) -> String {
|
||||
number.push(chars.next().unwrap());
|
||||
}
|
||||
result.push(u8::from_str_radix(&number, 16).unwrap() as char);
|
||||
},
|
||||
}
|
||||
'n' => result.push('\n'),
|
||||
'r' => result.push('\r'),
|
||||
't' => result.push('\t'),
|
||||
@@ -447,6 +461,28 @@ fn script_parser() -> impl Parser<Token, ast::Script, Error = ScriptError> + Clo
|
||||
_ => None,
|
||||
});
|
||||
|
||||
let product_op = just(Token::Op("*".to_string()))
|
||||
.to(ast::BinOp::Mul)
|
||||
.or(just(Token::Op("/".to_string())).to(ast::BinOp::Div))
|
||||
.or(just(Token::Op("#/".to_string())).to(ast::BinOp::DivU))
|
||||
.or(just(Token::Op("%".to_string())).to(ast::BinOp::Rem))
|
||||
.or(just(Token::Op("#%".to_string())).to(ast::BinOp::RemU))
|
||||
.boxed();
|
||||
let sum_op = just(Token::Op("+".to_string()))
|
||||
.to(ast::BinOp::Add)
|
||||
.or(just(Token::Op("-".to_string())).to(ast::BinOp::Sub))
|
||||
.boxed();
|
||||
let shift_op = just(Token::Op("<<".to_string()))
|
||||
.to(ast::BinOp::Shl)
|
||||
.or(just(Token::Op("#>>".to_string())).to(ast::BinOp::ShrU))
|
||||
.or(just(Token::Op(">>".to_string())).to(ast::BinOp::ShrS))
|
||||
.boxed();
|
||||
let bit_op = just(Token::Op("&".to_string()))
|
||||
.to(ast::BinOp::And)
|
||||
.or(just(Token::Op("|".to_string())).to(ast::BinOp::Or))
|
||||
.or(just(Token::Op("^".to_string())).to(ast::BinOp::Xor))
|
||||
.boxed();
|
||||
|
||||
let mut expression_out = None;
|
||||
let block = recursive(|block| {
|
||||
let mut block_expression = None;
|
||||
@@ -723,16 +759,7 @@ fn script_parser() -> impl Parser<Token, ast::Script, Error = ScriptError> + Clo
|
||||
|
||||
let op_product = memory_op
|
||||
.clone()
|
||||
.then(
|
||||
just(Token::Op("*".to_string()))
|
||||
.to(ast::BinOp::Mul)
|
||||
.or(just(Token::Op("/".to_string())).to(ast::BinOp::Div))
|
||||
.or(just(Token::Op("#/".to_string())).to(ast::BinOp::DivU))
|
||||
.or(just(Token::Op("%".to_string())).to(ast::BinOp::Rem))
|
||||
.or(just(Token::Op("#%".to_string())).to(ast::BinOp::RemU))
|
||||
.then(memory_op.clone())
|
||||
.repeated(),
|
||||
)
|
||||
.then(product_op.clone().then(memory_op.clone()).repeated())
|
||||
.foldl(|left, (op, right)| {
|
||||
let span = (left.span.0, left.span.1.start..right.span.1.end);
|
||||
ast::Expr::BinOp {
|
||||
@@ -746,13 +773,7 @@ fn script_parser() -> impl Parser<Token, ast::Script, Error = ScriptError> + Clo
|
||||
|
||||
let op_sum = op_product
|
||||
.clone()
|
||||
.then(
|
||||
just(Token::Op("+".to_string()))
|
||||
.to(ast::BinOp::Add)
|
||||
.or(just(Token::Op("-".to_string())).to(ast::BinOp::Sub))
|
||||
.then(op_product.clone())
|
||||
.repeated(),
|
||||
)
|
||||
.then(sum_op.clone().then(op_product.clone()).repeated())
|
||||
.foldl(|left, (op, right)| {
|
||||
let span = (left.span.0, left.span.1.start..right.span.1.end);
|
||||
ast::Expr::BinOp {
|
||||
@@ -766,14 +787,7 @@ fn script_parser() -> impl Parser<Token, ast::Script, Error = ScriptError> + Clo
|
||||
|
||||
let op_shift = op_sum
|
||||
.clone()
|
||||
.then(
|
||||
just(Token::Op("<<".to_string()))
|
||||
.to(ast::BinOp::Shl)
|
||||
.or(just(Token::Op("#>>".to_string())).to(ast::BinOp::ShrU))
|
||||
.or(just(Token::Op(">>".to_string())).to(ast::BinOp::ShrS))
|
||||
.then(op_sum.clone())
|
||||
.repeated(),
|
||||
)
|
||||
.then(shift_op.clone().then(op_sum.clone()).repeated())
|
||||
.foldl(|left, (op, right)| {
|
||||
let span = (left.span.0, left.span.1.start..right.span.1.end);
|
||||
ast::Expr::BinOp {
|
||||
@@ -815,14 +829,7 @@ fn script_parser() -> impl Parser<Token, ast::Script, Error = ScriptError> + Clo
|
||||
|
||||
let op_bit = op_cmp
|
||||
.clone()
|
||||
.then(
|
||||
just(Token::Op("&".to_string()))
|
||||
.to(ast::BinOp::And)
|
||||
.or(just(Token::Op("|".to_string())).to(ast::BinOp::Or))
|
||||
.or(just(Token::Op("^".to_string())).to(ast::BinOp::Xor))
|
||||
.then(op_cmp.clone())
|
||||
.repeated(),
|
||||
)
|
||||
.then(bit_op.clone().then(op_cmp.clone()).repeated())
|
||||
.foldl(|left, (op, right)| {
|
||||
let span = (left.span.0, left.span.1.start..right.span.1.end);
|
||||
ast::Expr::BinOp {
|
||||
@@ -867,11 +874,45 @@ fn script_parser() -> impl Parser<Token, ast::Script, Error = ScriptError> + Clo
|
||||
.map_with_span(|expr, span| expr.with_span(span))
|
||||
.boxed();
|
||||
|
||||
let assign_op = identifier
|
||||
.then(
|
||||
product_op
|
||||
.clone()
|
||||
.or(sum_op.clone())
|
||||
.or(shift_op.clone())
|
||||
.or(bit_op.clone()),
|
||||
)
|
||||
.then_ignore(just(Token::Op("=".to_string())))
|
||||
.then(expression.clone())
|
||||
.map_with_span(|((name, op), value), span| {
|
||||
ast::Expr::Assign {
|
||||
name: name.clone(),
|
||||
value: Box::new(
|
||||
ast::Expr::BinOp {
|
||||
left: Box::new(
|
||||
ast::Expr::Variable {
|
||||
name,
|
||||
local_id: None,
|
||||
}
|
||||
.with_span(span.clone()),
|
||||
),
|
||||
right: Box::new(value),
|
||||
op,
|
||||
}
|
||||
.with_span(span.clone()),
|
||||
),
|
||||
local_id: None,
|
||||
}
|
||||
.with_span(span)
|
||||
})
|
||||
.boxed();
|
||||
|
||||
block_expression
|
||||
.clone()
|
||||
.then(just(Token::Ctrl(';')).or_not())
|
||||
.map_with_span(|(expr, semi), span| (expr.with_span(span), semi.is_none()))
|
||||
.or(assign
|
||||
.or(assign_op)
|
||||
.or(expression.clone())
|
||||
.then(just(Token::Ctrl(';')).to(false)))
|
||||
.repeated()
|
||||
|
||||
15
test/xorshift.cwa
Normal file
15
test/xorshift.cwa
Normal file
@@ -0,0 +1,15 @@
|
||||
// simple test to see whether lazy/inline chains with the same variable compile correctly
|
||||
|
||||
fn xorshift(x: i32) -> i32 {
|
||||
let lazy x = x ^ (x << 13);
|
||||
let lazy x = x ^ (x #>> 17);
|
||||
let inline x = x ^ (x << 5);
|
||||
x
|
||||
}
|
||||
|
||||
fn xorshift2(x: i32) -> i32 {
|
||||
x ^= x << 13;
|
||||
x ^= x #>> 17;
|
||||
x ^= x << 5;
|
||||
x
|
||||
}
|
||||
Reference in New Issue
Block a user