implement unsigned operators

This commit is contained in:
2021-11-11 23:04:41 +01:00
parent d3e882cba0
commit 51cf8a8d28
7 changed files with 161 additions and 51 deletions

View File

@@ -9,14 +9,14 @@ fn random() -> i32 {
fn random64() -> i64 {
let state: i64;
randomState = (state := (
state := randomState ^ (randomState >> 12i64)
state := randomState ^ (randomState #>> 12i64)
) ^ (state << 25i64)
) ^ (state >> 27i64);
) ^ (state #>> 27i64);
randomState * 2685821657736338717i64
}
fn randomf() -> f32 {
f32.reinterpret_i32(1065353216 | (random() >> 9)) - 1 as f32
f32.reinterpret_i32(1065353216 | (random() #>> 9)) - 1 as f32
}
fn seed(s: i32) {
@@ -28,8 +28,8 @@ fn seed(s: i32) {
export fn tic(time: i32) {
let i: i32;
loop pixels {
seed(i + (time / 100) * 320);
i?120 = (randomf() * 256 as f32 + time as f32 / 10 as f32) as i32;
seed(i + (time / 10) * 320);
i?120 = (randomf() * 256 as f32 + time as f32 / 10 as f32) as i32 & 128;
branch_if (i := i + 1) < 320*256: pixels
}
}

View File

@@ -14,7 +14,7 @@ global mut s: f32 = 0.0;
global mut f: f32 = 0.0;
fn rng(state: i32) -> i32 {
94614859 * (state ^ (state >> 17))
94614859 * (state ^ (state #>> 17))
}
fn set_color(color: i32) -> i32 {
@@ -35,7 +35,7 @@ export fn update() {
loop lines {
?(8003-y) = (score := score / 10) % 10 + 48;
let defer z = (4000 / (y := y + 1) + pz) / 20;
let defer x = (rng(rng(rng(rng(z)))) >>> 30) as f32 - px;
let defer x = (rng(rng(rng(rng(z)))) >> 30) as f32 - px;
let defer w = 9 as f32 / sqrt(z as f32);
let defer rx = 80 + (y as f32 * x) as i32;
let defer rw = (y as f32 * w) as i32;
@@ -47,10 +47,10 @@ export fn update() {
if y == 120 & py > zero {
if x < -w | x > zero {
if pad & 2 { // (*)
pz = 30; // (*)
px = zero; // (*)
} // (*)
if pad & 2 {
pz = 30;
px = zero;
}
return;
}
py = zero;

View File

@@ -170,19 +170,25 @@ pub enum BinOp {
Sub,
Mul,
Div,
DivU,
Rem,
RemU,
And,
Or,
Xor,
Eq,
Ne,
Gt,
GtU,
Ge,
GeU,
Lt,
LtU,
Le,
Lsl,
Lsr,
Asr,
LeU,
Shl,
ShrU,
ShrS,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]

View File

@@ -18,7 +18,10 @@ fn fold_mem_location(mem_location: &mut ast::MemoryLocation) {
fn fold_expr(expr: &mut ast::Expression) {
use ast::BinOp::*;
match expr.expr {
ast::Expr::Block { ref mut statements, ref mut final_expression} => {
ast::Expr::Block {
ref mut statements,
ref mut final_expression,
} => {
for stmt in statements {
fold_expr(stmt);
}
@@ -43,13 +46,25 @@ fn fold_expr(expr: &mut ast::Expression) {
ast::Expr::UnaryOp { op, ref mut value } => {
fold_expr(value);
let result = match (op, &value.expr) {
(ast::UnaryOp::Negate, ast::Expr::I32Const(value)) => Some(ast::Expr::I32Const(-*value)),
(ast::UnaryOp::Negate, ast::Expr::I64Const(value)) => Some(ast::Expr::I64Const(-*value)),
(ast::UnaryOp::Negate, ast::Expr::F32Const(value)) => Some(ast::Expr::F32Const(-*value)),
(ast::UnaryOp::Negate, ast::Expr::F64Const(value)) => Some(ast::Expr::F64Const(-*value)),
(ast::UnaryOp::Not, ast::Expr::I32Const(value)) => Some(ast::Expr::I32Const((*value == 0) as i32)),
(ast::UnaryOp::Not, ast::Expr::I64Const(value)) => Some(ast::Expr::I32Const((*value == 0) as i32)),
_ => None
(ast::UnaryOp::Negate, ast::Expr::I32Const(value)) => {
Some(ast::Expr::I32Const(-*value))
}
(ast::UnaryOp::Negate, ast::Expr::I64Const(value)) => {
Some(ast::Expr::I64Const(-*value))
}
(ast::UnaryOp::Negate, ast::Expr::F32Const(value)) => {
Some(ast::Expr::F32Const(-*value))
}
(ast::UnaryOp::Negate, ast::Expr::F64Const(value)) => {
Some(ast::Expr::F64Const(-*value))
}
(ast::UnaryOp::Not, ast::Expr::I32Const(value)) => {
Some(ast::Expr::I32Const((*value == 0) as i32))
}
(ast::UnaryOp::Not, ast::Expr::I64Const(value)) => {
Some(ast::Expr::I32Const((*value == 0) as i32))
}
_ => None,
};
if let Some(result) = result {
expr.expr = result;
@@ -76,6 +91,13 @@ fn fold_expr(expr: &mut ast::Expression) {
return;
}
}
DivU => {
if let Some(result) = (left as u32).checked_div(right as u32) {
result as i32
} else {
return;
}
}
Rem => {
if let Some(result) = left.checked_rem(right) {
result
@@ -83,24 +105,35 @@ fn fold_expr(expr: &mut ast::Expression) {
return;
}
}
RemU => {
if let Some(result) = (left as u32).checked_rem(right as u32) {
result as i32
} else {
return;
}
}
And => left & right,
Or => left | right,
Xor => left ^ right,
Eq => (left == right) as i32,
Ne => (left != right) as i32,
Lt => (left < right) as i32,
LtU => ((left as u32) < (right as u32)) as i32,
Le => (left <= right) as i32,
LeU => ((left as u32) <= (right as u32)) as i32,
Gt => (left > right) as i32,
GtU => ((left as u32) > (right as u32)) as i32,
Ge => (left >= right) as i32,
Lsl => left << right,
Lsr => ((left as u32) >> right) as i32,
Asr => left >> right
GeU => ((left as u32) >= (right as u32)) as i32,
Shl => left << right,
ShrU => ((left as u32) >> right) as i32,
ShrS => left >> right,
};
expr.expr = ast::Expr::I32Const(result);
}
(&ast::Expr::I64Const(left), &ast::Expr::I64Const(right)) => {
use ast::Expr::*;
expr.expr = match op {
expr.expr = match op {
Add => I64Const(left.wrapping_add(right)),
Sub => I64Const(left.wrapping_sub(right)),
Mul => I64Const(left.wrapping_mul(right)),
@@ -111,6 +144,13 @@ fn fold_expr(expr: &mut ast::Expression) {
return;
}
}
DivU => {
if let Some(result) = (left as u64).checked_div(right as u64) {
I64Const(result as i64)
} else {
return;
}
}
Rem => {
if let Some(result) = left.checked_rem(right) {
I64Const(result)
@@ -118,18 +158,29 @@ fn fold_expr(expr: &mut ast::Expression) {
return;
}
}
RemU => {
if let Some(result) = (left as u64).checked_rem(right as u64) {
I64Const(result as i64)
} else {
return;
}
}
And => I64Const(left & right),
Or => I64Const(left | right),
Xor => I64Const(left ^ right),
Eq => I32Const((left == right) as i32),
Ne => I32Const((left != right) as i32),
Lt => I32Const((left < right) as i32),
LtU => I32Const(((left as u64) < (right as u64)) as i32),
Le => I32Const((left <= right) as i32),
LeU => I32Const(((left as u64) <= (right as u64)) as i32),
Gt => I32Const((left > right) as i32),
GtU => I32Const(((left as u64) > (right as u64)) as i32),
Ge => I32Const((left >= right) as i32),
Lsl => I64Const(left << right),
Lsr => I64Const(((left as u64) >> right) as i64),
Asr => I64Const(left >> right)
GeU => I32Const(((left as u64) >= (right as u64)) as i32),
Shl => I64Const(left << right),
ShrU => I64Const(((left as u64) >> right) as i64),
ShrS => I64Const(left >> right),
};
}
(&ast::Expr::F32Const(left), &ast::Expr::F32Const(right)) => {
@@ -139,7 +190,8 @@ fn fold_expr(expr: &mut ast::Expression) {
Sub => F32Const(left - right),
Mul => F32Const(left * right),
Div => F32Const(left / right),
Rem | And | Or | Xor | Lsl | Lsr | Asr => return,
Rem | And | Or | Xor | Shl | ShrU | ShrS | DivU | RemU | LtU | LeU
| GtU | GeU => return,
Eq => I32Const((left == right) as i32),
Ne => I32Const((left != right) as i32),
Lt => I32Const((left < right) as i32),
@@ -155,7 +207,8 @@ fn fold_expr(expr: &mut ast::Expression) {
Sub => F64Const(left - right),
Mul => F64Const(left * right),
Div => F64Const(left / right),
Rem | And | Or | Xor | Lsl | Lsr | Asr => return,
Rem | And | Or | Xor | Shl | ShrU | ShrS | DivU | RemU | LtU | LeU
| GtU | GeU => return,
Eq => I32Const((left == right) as i32),
Ne => I32Const((left != right) as i32),
Lt => I32Const((left < right) as i32),
@@ -167,7 +220,11 @@ fn fold_expr(expr: &mut ast::Expression) {
_ => (),
}
}
ast::Expr::I32Const(_) | ast::Expr::I64Const(_) | ast::Expr::F32Const(_) | ast::Expr::F64Const(_) | ast::Expr::Variable { .. } => (),
ast::Expr::I32Const(_)
| ast::Expr::I64Const(_)
| ast::Expr::F32Const(_)
| ast::Expr::F64Const(_)
| ast::Expr::Variable { .. } => (),
ast::Expr::Assign { ref mut value, .. } => fold_expr(value),
ast::Expr::LocalTee { ref mut value, .. } => fold_expr(value),
ast::Expr::Loop { ref mut block, .. } => fold_expr(block),
@@ -202,7 +259,9 @@ fn fold_expr(expr: &mut ast::Expression) {
fold_expr(if_false);
}
ast::Expr::If {
ref mut condition, ref mut if_true, ref mut if_false
ref mut condition,
ref mut if_true,
ref mut if_false,
} => {
fold_expr(condition);
fold_expr(if_true);
@@ -210,12 +269,17 @@ fn fold_expr(expr: &mut ast::Expression) {
fold_expr(if_false);
}
}
ast::Expr::Return { value: Some(ref mut value) } => fold_expr(value),
ast::Expr::Return {
value: Some(ref mut value),
} => fold_expr(value),
ast::Expr::Return { value: None } => (),
ast::Expr::First { ref mut value, ref mut drop } => {
ast::Expr::First {
ref mut value,
ref mut drop,
} => {
fold_expr(value);
fold_expr(drop);
}
ast::Expr::Error => unreachable!()
ast::Expr::Error => unreachable!(),
}
}

View File

@@ -413,43 +413,58 @@ fn emit_expression<'a>(ctx: &mut FunctionContext<'a>, expr: &'a ast::Expression)
(I32, Sub) => Instruction::I32Sub,
(I32, Mul) => Instruction::I32Mul,
(I32, Div) => Instruction::I32DivS,
(I32, DivU) => Instruction::I32DivU,
(I32, Rem) => Instruction::I32RemS,
(I32, RemU) => Instruction::I32RemU,
(I32, And) => Instruction::I32And,
(I32, Or) => Instruction::I32Or,
(I32, Xor) => Instruction::I32Xor,
(I32, Eq) => Instruction::I32Eq,
(I32, Ne) => Instruction::I32Neq,
(I32, Lt) => Instruction::I32LtS,
(I32, LtU) => Instruction::I32LtU,
(I32, Le) => Instruction::I32LeS,
(I32, LeU) => Instruction::I32LeU,
(I32, Gt) => Instruction::I32GtS,
(I32, GtU) => Instruction::I32GtU,
(I32, Ge) => Instruction::I32GeS,
(I32, Lsl) => Instruction::I32Shl,
(I32, Lsr) => Instruction::I32ShrU,
(I32, Asr) => Instruction::I32ShrS,
(I32, GeU) => Instruction::I32GeU,
(I32, Shl) => Instruction::I32Shl,
(I32, ShrU) => Instruction::I32ShrU,
(I32, ShrS) => Instruction::I32ShrS,
(I64, Add) => Instruction::I64Add,
(I64, Sub) => Instruction::I64Sub,
(I64, Mul) => Instruction::I64Mul,
(I64, Div) => Instruction::I64DivS,
(I64, DivU) => Instruction::I64DivU,
(I64, Rem) => Instruction::I64RemS,
(I64, RemU) => Instruction::I64RemU,
(I64, And) => Instruction::I64And,
(I64, Or) => Instruction::I64Or,
(I64, Xor) => Instruction::I64Xor,
(I64, Eq) => Instruction::I64Eq,
(I64, Ne) => Instruction::I64Neq,
(I64, Lt) => Instruction::I64LtS,
(I64, LtU) => Instruction::I64LtU,
(I64, Le) => Instruction::I64LeS,
(I64, LeU) => Instruction::I64LeU,
(I64, Gt) => Instruction::I64GtS,
(I64, GtU) => Instruction::I64GtU,
(I64, Ge) => Instruction::I64GeS,
(I64, Lsl) => Instruction::I64Shl,
(I64, Lsr) => Instruction::I64ShrU,
(I64, Asr) => Instruction::I64ShrS,
(I64, GeU) => Instruction::I64GeU,
(I64, Shl) => Instruction::I64Shl,
(I64, ShrU) => Instruction::I64ShrU,
(I64, ShrS) => Instruction::I64ShrS,
(F32, Add) => Instruction::F32Add,
(F32, Sub) => Instruction::F32Sub,
(F32, Mul) => Instruction::F32Mul,
(F32, Div) => Instruction::F32Div,
(F32, Rem | And | Or | Xor | Lsl | Lsr | Asr) => unreachable!(),
(
F32,
DivU | Rem | RemU | And | Or | Xor | Shl | ShrU | ShrS | LtU | LeU | GtU | GeU,
) => unreachable!(),
(F32, Eq) => Instruction::F32Eq,
(F32, Ne) => Instruction::F32Neq,
(F32, Lt) => Instruction::F32Lt,
@@ -461,7 +476,10 @@ fn emit_expression<'a>(ctx: &mut FunctionContext<'a>, expr: &'a ast::Expression)
(F64, Sub) => Instruction::F64Sub,
(F64, Mul) => Instruction::F64Mul,
(F64, Div) => Instruction::F64Div,
(F64, Rem | And | Or | Xor | Lsl | Lsr | Asr) => unreachable!(),
(
F64,
DivU | Rem | RemU | And | Or | Xor | Shl | ShrU | ShrS | LtU | LeU | GtU | GeU,
) => unreachable!(),
(F64, Eq) => Instruction::F64Eq,
(F64, Ne) => Instruction::F64Neq,
(F64, Lt) => Instruction::F64Lt,

View File

@@ -192,7 +192,7 @@ fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = Simple<char>> {
.collect::<String>()
.map(Token::Str);
let op = one_of("+-*/%&^|<=>".chars())
let op = one_of("+-*/%&^|<=>#".chars())
.repeated()
.at_least(1)
.or(just(':').chain(just('=')))
@@ -574,7 +574,9 @@ fn script_parser() -> impl Parser<Token, ast::Script, Error = Simple<Token>> + C
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(),
)
@@ -613,9 +615,9 @@ fn script_parser() -> impl Parser<Token, ast::Script, Error = Simple<Token>> + C
.clone()
.then(
just(Token::Op("<<".to_string()))
.to(ast::BinOp::Lsl)
.or(just(Token::Op(">>".to_string())).to(ast::BinOp::Lsr))
.or(just(Token::Op(">>>".to_string())).to(ast::BinOp::Asr))
.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(),
)
@@ -637,9 +639,13 @@ fn script_parser() -> impl Parser<Token, ast::Script, Error = Simple<Token>> + C
.to(ast::BinOp::Eq)
.or(just(Token::Op("!=".to_string())).to(ast::BinOp::Ne))
.or(just(Token::Op("<".to_string())).to(ast::BinOp::Lt))
.or(just(Token::Op("#<".to_string())).to(ast::BinOp::LtU))
.or(just(Token::Op("<=".to_string())).to(ast::BinOp::Le))
.or(just(Token::Op("#<=".to_string())).to(ast::BinOp::LeU))
.or(just(Token::Op(">".to_string())).to(ast::BinOp::Gt))
.or(just(Token::Op("#>".to_string())).to(ast::BinOp::GtU))
.or(just(Token::Op(">=".to_string())).to(ast::BinOp::Ge))
.or(just(Token::Op("#>=".to_string())).to(ast::BinOp::GeU))
.then(op_shift.clone())
.repeated(),
)

View File

@@ -429,7 +429,7 @@ fn tc_expression(context: &mut Context, expr: &mut ast::Expression) -> Result<()
use ast::BinOp::*;
match op {
Add | Sub | Mul | Div => left.type_,
Rem | And | Or | Xor | Lsl | Lsr | Asr => {
Rem | And | Or | Xor | Shl | ShrU | ShrS | DivU | RemU => {
if left.type_ != Some(I32) && left.type_ != Some(I64) {
return type_mismatch(
Some(I32),
@@ -443,6 +443,19 @@ fn tc_expression(context: &mut Context, expr: &mut ast::Expression) -> Result<()
}
}
Eq | Ne | Lt | Le | Gt | Ge => Some(I32),
LtU | LeU | GtU | GeU => {
if left.type_ != Some(I32) && left.type_ != Some(I64) {
return type_mismatch(
Some(I32),
&left.span,
left.type_,
&left.span,
context.source,
);
} else {
Some(I32)
}
}
}
}
ast::Expr::Variable(ref name) => {
@@ -687,7 +700,10 @@ fn tc_expression(context: &mut Context, expr: &mut ast::Expression) -> Result<()
}
None
}
ast::Expr::First { ref mut value, ref mut drop } => {
ast::Expr::First {
ref mut value,
ref mut drop,
} => {
tc_expression(context, value)?;
tc_expression(context, drop)?;
value.type_