@@ -8553,3 +8553,270 @@ fn (mut c Checker) ensure_type_exists(typ ast.Type, pos token.Position) ? {
85538553 else {}
85548554 }
85558555}
8556+
8557+ // comptime const eval
8558+ fn eval_comptime_const_expr (expr ast.Expr, nlevel int ) ? ast.ComptTimeConstValue {
8559+ if nlevel > 100 {
8560+ // protect against a too deep comptime eval recursion
8561+ return none
8562+ }
8563+ match expr {
8564+ ast.IntegerLiteral {
8565+ x := expr.val.u64 ()
8566+ if x > 9223372036854775807 {
8567+ return x
8568+ }
8569+ return expr.val.i64 ()
8570+ }
8571+ ast.StringLiteral {
8572+ return expr.val
8573+ }
8574+ ast.CharLiteral {
8575+ runes := expr.val.runes ()
8576+ if runes.len > 0 {
8577+ return runes[0 ]
8578+ }
8579+ return none
8580+ }
8581+ ast.Ident {
8582+ if expr.obj is ast.ConstField {
8583+ // an existing constant?
8584+ return eval_comptime_const_expr (expr.obj.expr, nlevel + 1 )
8585+ }
8586+ }
8587+ ast.CastExpr {
8588+ cast_expr_value := eval_comptime_const_expr (expr.expr, nlevel + 1 ) or { return none }
8589+ if expr.typ == ast.i8_ type {
8590+ return cast_expr_value.i8 () or { return none }
8591+ }
8592+ if expr.typ == ast.i16_ type {
8593+ return cast_expr_value.i16 () or { return none }
8594+ }
8595+ if expr.typ == ast.int_type {
8596+ return cast_expr_value.int () or { return none }
8597+ }
8598+ if expr.typ == ast.i64_ type {
8599+ return cast_expr_value.i64 () or { return none }
8600+ }
8601+ //
8602+ if expr.typ == ast.byte_type {
8603+ return cast_expr_value.byte () or { return none }
8604+ }
8605+ if expr.typ == ast.u16_ type {
8606+ return cast_expr_value.u16 () or { return none }
8607+ }
8608+ if expr.typ == ast.u32_ type {
8609+ return cast_expr_value.u32 () or { return none }
8610+ }
8611+ if expr.typ == ast.u64_ type {
8612+ return cast_expr_value.u64 () or { return none }
8613+ }
8614+ //
8615+ if expr.typ == ast.f32_ type {
8616+ return cast_expr_value.f32 () or { return none }
8617+ }
8618+ if expr.typ == ast.f64_ type {
8619+ return cast_expr_value.f64 () or { return none }
8620+ }
8621+ }
8622+ ast.InfixExpr {
8623+ left := eval_comptime_const_expr (expr.left, nlevel + 1 ) ?
8624+ right := eval_comptime_const_expr (expr.right, nlevel + 1 ) ?
8625+ if left is string && right is string {
8626+ match expr.op {
8627+ .plus {
8628+ return left + right
8629+ }
8630+ else {
8631+ return none
8632+ }
8633+ }
8634+ } else if left is u64 && right is i64 {
8635+ match expr.op {
8636+ .plus { return i64 (left) + i64 (right) }
8637+ .minus { return i64 (left) - i64 (right) }
8638+ .mul { return i64 (left) * i64 (right) }
8639+ .div { return i64 (left) / i64 (right) }
8640+ .mod { return i64 (left) % i64 (right) }
8641+ .xor { return i64 (left) ^ i64 (right) }
8642+ .pipe { return i64 (left) | i64 (right) }
8643+ .amp { return i64 (left) & i64 (right) }
8644+ .left_shift { return i64 (left) << i64 (right) }
8645+ .right_shift { return i64 (left) >> i64 (right) }
8646+ else { return none }
8647+ }
8648+ } else if left is i64 && right is u64 {
8649+ match expr.op {
8650+ .plus { return i64 (left) + i64 (right) }
8651+ .minus { return i64 (left) - i64 (right) }
8652+ .mul { return i64 (left) * i64 (right) }
8653+ .div { return i64 (left) / i64 (right) }
8654+ .mod { return i64 (left) % i64 (right) }
8655+ .xor { return i64 (left) ^ i64 (right) }
8656+ .pipe { return i64 (left) | i64 (right) }
8657+ .amp { return i64 (left) & i64 (right) }
8658+ .left_shift { return i64 (left) << i64 (right) }
8659+ .right_shift { return i64 (left) >> i64 (right) }
8660+ else { return none }
8661+ }
8662+ } else if left is u64 && right is u64 {
8663+ match expr.op {
8664+ .plus { return left + right }
8665+ .minus { return left - right }
8666+ .mul { return left * right }
8667+ .div { return left / right }
8668+ .mod { return left % right }
8669+ .xor { return left ^ right }
8670+ .pipe { return left | right }
8671+ .amp { return left & right }
8672+ .left_shift { return left << right }
8673+ .right_shift { return left >> right }
8674+ else { return none }
8675+ }
8676+ } else if left is i64 && right is i64 {
8677+ match expr.op {
8678+ .plus { return left + right }
8679+ .minus { return left - right }
8680+ .mul { return left * right }
8681+ .div { return left / right }
8682+ .mod { return left % right }
8683+ .xor { return left ^ right }
8684+ .pipe { return left | right }
8685+ .amp { return left & right }
8686+ .left_shift { return left << right }
8687+ .right_shift { return left >> right }
8688+ else { return none }
8689+ }
8690+ } else if left is byte && right is byte {
8691+ match expr.op {
8692+ .plus { return left + right }
8693+ .minus { return left - right }
8694+ .mul { return left * right }
8695+ .div { return left / right }
8696+ .mod { return left % right }
8697+ .xor { return left ^ right }
8698+ .pipe { return left | right }
8699+ .amp { return left & right }
8700+ .left_shift { return left << right }
8701+ .right_shift { return left >> right }
8702+ else { return none }
8703+ }
8704+ }
8705+ }
8706+ else {
8707+ // eprintln('>>> nlevel: $nlevel | another $expr.type_name() | $expr ')
8708+ return none
8709+ }
8710+ }
8711+ return none
8712+ }
8713+
8714+ fn (mut c Checker) check_noreturn_fn_decl (mut node ast.FnDecl) {
8715+ if ! node.is_noreturn {
8716+ return
8717+ }
8718+ if node.no_body {
8719+ return
8720+ }
8721+ if node.return_type != ast.void_type {
8722+ c.error ('[noreturn] functions cannot have return types' , node.pos)
8723+ }
8724+ if uses_return_stmt (node.stmts) {
8725+ c.error ('[noreturn] functions cannot use return statements' , node.pos)
8726+ }
8727+ if node.stmts.len != 0 {
8728+ mut is_valid_end_of_noreturn_fn := false
8729+ last_stmt := node.stmts.last ()
8730+ match last_stmt {
8731+ ast.ExprStmt {
8732+ if last_stmt.expr is ast.CallExpr {
8733+ if last_stmt.expr.should_be_skipped {
8734+ c.error ('[noreturn] functions cannot end with a skippable `[if ..]` call' ,
8735+ last_stmt.pos)
8736+ return
8737+ }
8738+ if last_stmt.expr.is_noreturn {
8739+ is_valid_end_of_noreturn_fn = true
8740+ }
8741+ }
8742+ }
8743+ ast.ForStmt {
8744+ if last_stmt.is_inf && last_stmt.stmts.len == 0 {
8745+ is_valid_end_of_noreturn_fn = true
8746+ }
8747+ }
8748+ else {}
8749+ }
8750+ if ! is_valid_end_of_noreturn_fn {
8751+ c.error ('[noreturn] functions should end with a call to another [noreturn] function, or with an infinite `for {}` loop' ,
8752+ last_stmt.pos)
8753+ return
8754+ }
8755+ }
8756+ }
8757+
8758+ fn uses_return_stmt (stmts []ast.Stmt) bool {
8759+ if stmts.len == 0 {
8760+ return false
8761+ }
8762+ for stmt in stmts {
8763+ match stmt {
8764+ ast.Return {
8765+ return true
8766+ }
8767+ ast.Block {
8768+ if uses_return_stmt (stmt.stmts) {
8769+ return true
8770+ }
8771+ }
8772+ ast.ExprStmt {
8773+ match stmt.expr {
8774+ ast.CallExpr {
8775+ if uses_return_stmt (stmt.expr.or_block.stmts) {
8776+ return true
8777+ }
8778+ }
8779+ ast.MatchExpr {
8780+ for b in stmt.expr.branches {
8781+ if uses_return_stmt (b.stmts) {
8782+ return true
8783+ }
8784+ }
8785+ }
8786+ ast.SelectExpr {
8787+ for b in stmt.expr.branches {
8788+ if uses_return_stmt (b.stmts) {
8789+ return true
8790+ }
8791+ }
8792+ }
8793+ ast.IfExpr {
8794+ for b in stmt.expr.branches {
8795+ if uses_return_stmt (b.stmts) {
8796+ return true
8797+ }
8798+ }
8799+ }
8800+ else {}
8801+ }
8802+ }
8803+ ast.ForStmt {
8804+ if uses_return_stmt (stmt.stmts) {
8805+ return true
8806+ }
8807+ }
8808+ ast.ForCStmt {
8809+ if uses_return_stmt (stmt.stmts) {
8810+ return true
8811+ }
8812+ }
8813+ ast.ForInStmt {
8814+ if uses_return_stmt (stmt.stmts) {
8815+ return true
8816+ }
8817+ }
8818+ else {}
8819+ }
8820+ }
8821+ return false
8822+ }
0 commit comments