🐐 TEMPTA/CAPE
This commit is contained in:
@@ -1045,6 +1045,45 @@ class PerStatement(Node):
|
||||
return vtable, last_val
|
||||
|
||||
|
||||
class TemptaStatement(Node):
|
||||
def __init__(self, try_statements, error_var, catch_statements) -> None:
|
||||
self.try_statements = try_statements
|
||||
self.error_var = error_var
|
||||
self.catch_statements = catch_statements
|
||||
|
||||
def __eq__(self, other):
|
||||
return (type(self) == type(other)
|
||||
and self.try_statements == other.try_statements
|
||||
and self.error_var == other.error_var
|
||||
and self.catch_statements == other.catch_statements)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
try_stmts = f"try([{rep_join(self.try_statements)}])"
|
||||
catch_stmts = f"catch([{rep_join(self.catch_statements)}])"
|
||||
tempta_string = rep_join([try_stmts, repr(self.error_var), catch_stmts])
|
||||
return f"Tempta({tempta_string})"
|
||||
|
||||
def print(self):
|
||||
try_body = "\n".join(s.print() for s in self.try_statements)
|
||||
catch_body = "\n".join(s.print() for s in self.catch_statements)
|
||||
return f"TEMPTA {{\n{try_body}\n}} CAPE {self.error_var.print()} {{\n{catch_body}\n}}"
|
||||
|
||||
def _eval(self, vtable):
|
||||
last_val = ValNul()
|
||||
try:
|
||||
for statement in self.try_statements:
|
||||
vtable, last_val = statement.eval(vtable)
|
||||
if vtable["#return"] is not None or vtable["#break"] or vtable["#continue"]:
|
||||
return vtable, last_val
|
||||
except CentvrionError as e:
|
||||
vtable[self.error_var.name] = ValStr(str(e))
|
||||
for statement in self.catch_statements:
|
||||
vtable, last_val = statement.eval(vtable)
|
||||
if vtable["#return"] is not None or vtable["#break"] or vtable["#continue"]:
|
||||
return vtable, last_val
|
||||
return vtable, last_val
|
||||
|
||||
|
||||
class Invoca(Node):
|
||||
def __init__(self, callee, parameters) -> None:
|
||||
self.callee = callee
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from centvrion.ast_nodes import (
|
||||
Designa, DesignaIndex, DesignaDestructure, SiStatement, DumStatement,
|
||||
PerStatement, Defini, Redi, Erumpe, Continva, ExpressionStatement, ID,
|
||||
PerStatement, TemptaStatement, Defini, Redi, Erumpe, Continva,
|
||||
ExpressionStatement, ID,
|
||||
)
|
||||
from centvrion.compiler.emit_expr import emit_expr
|
||||
|
||||
@@ -125,6 +126,24 @@ def emit_stmt(node, ctx):
|
||||
if isinstance(node, Continva):
|
||||
return ["continue;"]
|
||||
|
||||
if isinstance(node, TemptaStatement):
|
||||
lines = [
|
||||
"_cent_try_depth++;",
|
||||
"if (setjmp(_cent_try_stack[_cent_try_depth - 1]) == 0) {",
|
||||
]
|
||||
try_lines = _emit_body(node.try_statements, ctx)
|
||||
lines += [f" {l}" for l in try_lines]
|
||||
lines += [
|
||||
" _cent_try_depth--;",
|
||||
"} else {",
|
||||
" _cent_try_depth--;",
|
||||
f' cent_scope_set(&_scope, "{node.error_var.name}", cent_str(_cent_error_msg));',
|
||||
]
|
||||
catch_lines = _emit_body(node.catch_statements, ctx)
|
||||
lines += [f" {l}" for l in catch_lines]
|
||||
lines += ["}"]
|
||||
return lines
|
||||
|
||||
if isinstance(node, ExpressionStatement):
|
||||
lines, _ = emit_expr(node.expression, ctx)
|
||||
return lines
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
CentArena *cent_arena;
|
||||
int cent_magnvm = 0;
|
||||
|
||||
jmp_buf _cent_try_stack[CENT_TRY_STACK_MAX];
|
||||
int _cent_try_depth = 0;
|
||||
const char *_cent_error_msg = NULL;
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Arena allocator */
|
||||
/* ------------------------------------------------------------------ */
|
||||
@@ -50,11 +54,19 @@ void *cent_arena_alloc(CentArena *a, size_t n) {
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
void cent_type_error(const char *msg) {
|
||||
if (_cent_try_depth > 0) {
|
||||
_cent_error_msg = msg;
|
||||
longjmp(_cent_try_stack[_cent_try_depth - 1], 1);
|
||||
}
|
||||
fprintf(stderr, "CENTVRION type error: %s\n", msg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void cent_runtime_error(const char *msg) {
|
||||
if (_cent_try_depth > 0) {
|
||||
_cent_error_msg = msg;
|
||||
longjmp(_cent_try_stack[_cent_try_depth - 1], 1);
|
||||
}
|
||||
fprintf(stderr, "CENTVRION error: %s\n", msg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Types */
|
||||
@@ -145,8 +146,13 @@ static inline CentValue cent_dict_val(CentValue *keys, CentValue *vals, int len,
|
||||
/* Error handling */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
void cent_type_error(const char *msg); /* type mismatch → exit(1) */
|
||||
void cent_runtime_error(const char *msg); /* runtime fault → exit(1) */
|
||||
#define CENT_TRY_STACK_MAX 64
|
||||
extern jmp_buf _cent_try_stack[];
|
||||
extern int _cent_try_depth;
|
||||
extern const char *_cent_error_msg;
|
||||
|
||||
void cent_type_error(const char *msg); /* type mismatch → longjmp or exit(1) */
|
||||
void cent_runtime_error(const char *msg); /* runtime fault → longjmp or exit(1) */
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Truthiness — conditions must be booleans; anything else is a fault */
|
||||
|
||||
@@ -6,6 +6,7 @@ keyword_tokens = [("KEYWORD_"+i, i) for i in [
|
||||
"AETERNVM",
|
||||
"ALVID",
|
||||
"AVGE",
|
||||
"CAPE",
|
||||
"AVT",
|
||||
"DEFINI",
|
||||
"DESIGNA",
|
||||
@@ -32,6 +33,7 @@ keyword_tokens = [("KEYWORD_"+i, i) for i in [
|
||||
"SI",
|
||||
"TVNC",
|
||||
"TABVLA",
|
||||
"TEMPTA",
|
||||
"VSQVE",
|
||||
"VT",
|
||||
"VERITAS",
|
||||
|
||||
@@ -163,6 +163,7 @@ class Parser():
|
||||
@self.pg.production('statement : dum_statement')
|
||||
@self.pg.production('statement : donicum_statement')
|
||||
@self.pg.production('statement : si_statement')
|
||||
@self.pg.production('statement : tempta_statement')
|
||||
def nested_statements(tokens):
|
||||
return tokens[0]
|
||||
|
||||
@@ -203,6 +204,10 @@ class Parser():
|
||||
def per(tokens):
|
||||
return ast_nodes.PerStatement(tokens[3], tokens[1], tokens[6])
|
||||
|
||||
@self.pg.production('tempta_statement : KEYWORD_TEMPTA SYMBOL_LCURL statements SYMBOL_RCURL KEYWORD_CAPE id SYMBOL_LCURL statements SYMBOL_RCURL')
|
||||
def tempta(tokens):
|
||||
return ast_nodes.TemptaStatement(tokens[2], tokens[5], tokens[7])
|
||||
|
||||
@self.pg.production('donicum_statement : KEYWORD_DONICVM id KEYWORD_VT expression KEYWORD_VSQVE expression KEYWORD_FACE SYMBOL_LCURL statements SYMBOL_RCURL')
|
||||
def donicum(tokens):
|
||||
range_array = ast_nodes.DataRangeArray(tokens[3], tokens[5])
|
||||
|
||||
Reference in New Issue
Block a user