Skip to content

Commit

Permalink
sema: check unary expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
StunxFS committed Jun 30, 2024
1 parent 02de7e0 commit 563bba3
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 3 deletions.
3 changes: 3 additions & 0 deletions bsc/AST.py
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,7 @@ def __init__(self, op, right, pos):
self.op = op
self.right = right
self.pos = pos
self.typ = None

def __str__(self):
return f"{self.op}{self.right}"
Expand All @@ -457,6 +458,7 @@ def __init__(self, left, op, right, pos):
self.op = op
self.right = right
self.pos = pos
self.typ = None

def __str__(self):
return f"{self.left} {self.op} {self.right}"
Expand Down Expand Up @@ -554,6 +556,7 @@ def __init__(self, lefts, op, right, pos):
self.op = op
self.right = right
self.pos = pos
self.typ = None

def __str__(self):
return f"{', '.join([str(left) for left in self.lefts])} {self.op} {str(self.right)}"
Expand Down
6 changes: 4 additions & 2 deletions bsc/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ def _format(pos, kind, kindc, msg):
), msg
)

def error(msg, pos):
def error(msg, pos, notes_ = []):
global errors
utils.eprint(_format(pos, "error:", utils.red, msg))
notes(notes_)
errors += 1

def warn(msg, pos):
def warn(msg, pos, notes_ = []):
utils.eprint(_format(pos, "warning:", utils.yellow, msg))
notes(notes_)

def notes(notes):
for i, note in enumerate(notes):
Expand Down
30 changes: 29 additions & 1 deletion bsc/sema.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,12 @@ def check_stmt(self, stmt):
def check_expr(self, expr):
if self.first_pass and not isinstance(expr, BlockExpr):
return self.ctx.void_type

if isinstance(expr, ParExpr):
expr.typ = self.check_expr(expr.expr)
elif isinstance(expr, AssignExpr):
#self.check_expr(expr.lefts)
self.check_expr(expr.right)
expr.typ = self.ctx.void_type
elif isinstance(expr, NilLiteral):
expr.typ = self.ctx.nil_type
elif isinstance(expr, BoolLiteral):
Expand All @@ -218,6 +221,31 @@ def check_expr(self, expr):
expr.typ = self.check_expr(expr.expr)
else:
expr.typ = self.ctx.void_type
elif isinstance(expr, UnaryExpr):
right_t = self.check_expr(expr.right)
match expr.op:
case UnaryOp.bang:
if right_t != self.ctx.bool_type:
report.error(
f"operator `!` is not defined for type `{right_t}`",
expr.pos,
["operator `!` is only defined for type `bool`"]
)
case UnaryOp.minus:
if right_t not in (self.ctx.int_type, self.ctx.float_type):
report.error(
f"operator `-` is not defined for type `{right_t}`",
expr.pos, [
"operator `-` is only defined for `int` and `float` types"
]
)
case UnaryOp.bit_not:
if right_t != self.ctx.int_type:
report.error(
f"operator `~` is not defined for type `{right_t}`",
expr.pos,
["operator `~` is only defined for type `int`"]
)
else:
expr.typ = self.ctx.void_type # tmp
return expr.typ
Expand Down
5 changes: 5 additions & 0 deletions tests/invalid_code/unary_expr.bs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fn main() {
_ = ~1.0;
_ = !1;
_ = -"";
}
6 changes: 6 additions & 0 deletions tests/invalid_code/unary_expr.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
tests/invalid_code/unary_expr.bs:2:10: error: operator `~` is not defined for type `float`
└ note: operator `~` is only defined for type `int`
tests/invalid_code/unary_expr.bs:3:10: error: operator `!` is not defined for type `int`
└ note: operator `!` is only defined for type `bool`
tests/invalid_code/unary_expr.bs:4:10: error: operator `-` is not defined for type `string`
└ note: operator `-` is only defined for `int` and `float` types

0 comments on commit 563bba3

Please sign in to comment.