unary minus
This commit is contained in:
@@ -125,7 +125,7 @@ eval_constant :: proc(checker: ^Checker, expr_id: ast.Expr_Id) -> Constant {
|
||||
continue
|
||||
}
|
||||
expr := checker.ast_module.exprs[frame.expr]
|
||||
if expr.kind != .Add {
|
||||
if expr.kind != .Add && expr.kind != .Negate {
|
||||
result := Constant{kind = .Not_Constant}
|
||||
if expr.kind == .Integer {
|
||||
result = Constant{kind = .Value, value = i128(expr.integer)}
|
||||
@@ -142,6 +142,22 @@ eval_constant :: proc(checker: ^Checker, expr_id: ast.Expr_Id) -> Constant {
|
||||
}
|
||||
continue
|
||||
}
|
||||
if frame.stage == 1 && expr.kind == .Negate {
|
||||
operand := Constant{kind = .Not_Constant}
|
||||
if expr.left != ast.INVALID_EXPR && int(expr.left) < len(checker.constants) {
|
||||
operand = checker.constants[expr.left]
|
||||
}
|
||||
result := Constant{kind = .Not_Constant}
|
||||
if operand.kind == .Overflow {
|
||||
result = Constant{kind = .Overflow}
|
||||
} else if operand.kind == .Value {
|
||||
value, overflow := intrinsics.overflow_sub(i128(0), operand.value)
|
||||
result = Constant{kind = .Overflow} if overflow else Constant{kind = .Value, value = value}
|
||||
}
|
||||
checker.constants[frame.expr] = result
|
||||
_ = pop(&stack)
|
||||
continue
|
||||
}
|
||||
if frame.stage == 1 {
|
||||
stack[frame_index].stage = 2
|
||||
if expr.right != ast.INVALID_EXPR && int(expr.right) < len(checker.ast_module.exprs) &&
|
||||
@@ -407,6 +423,8 @@ mark_expr_imports_used :: proc(checker: ^Checker, expr_id: ast.Expr_Id, file: as
|
||||
switch expr.kind {
|
||||
case .Call:
|
||||
append(&stack, ..expr.args)
|
||||
case .Negate:
|
||||
append(&stack, expr.left)
|
||||
case .Add:
|
||||
append(&stack, expr.left, expr.right)
|
||||
case .Invalid, .Integer, .Name:
|
||||
@@ -644,7 +662,10 @@ infer_expr :: proc(
|
||||
last = types.INVALID
|
||||
_ = pop(&stack)
|
||||
case .Integer:
|
||||
last = types.smallest_signed_for_literal(expr.integer)
|
||||
last = types.I64
|
||||
if expr.integer <= 0x7fff_ffff_ffff_ffff {
|
||||
last = types.smallest_signed_for_literal(i64(expr.integer))
|
||||
}
|
||||
_ = pop(&stack)
|
||||
case .Name:
|
||||
last = types.INVALID
|
||||
@@ -661,6 +682,9 @@ infer_expr :: proc(
|
||||
}
|
||||
}
|
||||
_ = pop(&stack)
|
||||
case .Negate:
|
||||
stack[frame_index].stage = 5
|
||||
append(&stack, Infer_Frame{expr=expr.left, template=ast.INVALID_FUNCTION})
|
||||
case .Add:
|
||||
stack[frame_index].stage = 1
|
||||
append(&stack, Infer_Frame{expr=expr.left, template=ast.INVALID_FUNCTION})
|
||||
@@ -690,6 +714,13 @@ infer_expr :: proc(
|
||||
}
|
||||
continue
|
||||
}
|
||||
if frame.stage == 5 {
|
||||
if !types.is_signed(last) {
|
||||
last = types.INVALID
|
||||
}
|
||||
_ = pop(&stack)
|
||||
continue
|
||||
}
|
||||
if frame.stage == 1 {
|
||||
stack[frame_index].left = last
|
||||
stack[frame_index].stage = 2
|
||||
@@ -1097,6 +1128,9 @@ build_expr :: proc(
|
||||
}
|
||||
}
|
||||
_ = pop(&stack)
|
||||
case .Negate:
|
||||
stack[frame_index].stage = 5
|
||||
append(&stack, Build_Expr_Frame{expr=expr.left, expected=types.INVALID, template=ast.INVALID_FUNCTION})
|
||||
case .Add:
|
||||
stack[frame_index].stage = 1
|
||||
append(&stack, Build_Expr_Frame{expr=expr.left, expected=types.INVALID, template=ast.INVALID_FUNCTION})
|
||||
@@ -1147,6 +1181,24 @@ build_expr :: proc(
|
||||
}
|
||||
continue
|
||||
}
|
||||
if frame.stage == 5 {
|
||||
operand := last
|
||||
operand_type := checker.module.exprs[operand].type
|
||||
if !types.is_signed(operand_type) {
|
||||
id := source.add(checker.diagnostics, expr.span, "negation requires a signed integer")
|
||||
last = invalid_hir_expr(checker, expr.span, id)
|
||||
} else {
|
||||
last = add_hir_expr(checker, hir.Expr{
|
||||
kind=.Negate, span=expr.span, type=operand_type, left=operand,
|
||||
target=hir.INVALID_REF, right=hir.INVALID_EXPR, diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
if types.is_signed(frame.expected) {
|
||||
last = coerce_expr(checker, last, frame.expected, expr.span)
|
||||
}
|
||||
}
|
||||
_ = pop(&stack)
|
||||
continue
|
||||
}
|
||||
if frame.stage == 1 {
|
||||
stack[frame_index].left = last
|
||||
stack[frame_index].stage = 2
|
||||
|
||||
Reference in New Issue
Block a user