Skip to content

Commit

Permalink
Merge pull request #128 from angelcaru/null
Browse files Browse the repository at this point in the history
Add dedicated `null` datatype (#127)
  • Loading branch information
Almas-Ali authored May 1, 2024
2 parents 182f45b + 6132b2e commit f976787
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 34 deletions.
2 changes: 1 addition & 1 deletion core/builtin_classes/file_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def close(ctx):
res = RTResult()
self = ctx.symbol_table.get("this")
self.file.close()
return res.success(Number.null())
return res.success(Null.null())

@args([])
@method
Expand Down
28 changes: 19 additions & 9 deletions core/builtin_funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def execute_print(self, exec_ctx):
value = exec_ctx.symbol_table.get("value")

print(value)
return RTResult().success(Number.null())
return RTResult().success(Null.null())

@args(["value"])
def execute_print_ret(self, exec_ctx):
Expand All @@ -95,7 +95,7 @@ def execute_input_int(self, exec_ctx):
@args([])
def execute_clear(self, exec_ctx):
os.system("cls" if os.name == "nt" else "clear")
return RTResult().success(Number.null())
return RTResult().success(Null.null())

@args(["value"])
def execute_is_number(self, exec_ctx):
Expand Down Expand Up @@ -143,7 +143,7 @@ def execute_arr_append(self, exec_ctx):
return RTResult().failure(RTError(self.pos_start, self.pos_end, "First argument must be array", exec_ctx))

array_.elements.append(value)
return RTResult().success(Number.null())
return RTResult().success(Null.null())

@args(["array", "index"], [None, Number(-1)])
def execute_arr_pop(self, exec_ctx):
Expand Down Expand Up @@ -181,7 +181,7 @@ def execute_arr_extend(self, exec_ctx):
return RTResult().failure(RTError(self.pos_start, self.pos_end, "Second argument must be array", exec_ctx))

arrayA.elements.extend(arrayB.elements)
return RTResult().success(Number.null())
return RTResult().success(Null.null())

@args(["array", "index"])
def execute_arr_find(self, exec_ctx):
Expand Down Expand Up @@ -350,7 +350,7 @@ def execute_pyapi(self, exec_ctx):
res.register(PyAPI(code.value).set_pos(self.pos_start, self.pos_end).set_context(self.context).pyapi(ns))
if res.should_return():
return res
return res.success(Number.null())
return res.success(Null.null())

@args([])
def execute_sys_args(self, exec_ctx):
Expand Down Expand Up @@ -416,12 +416,21 @@ def execute_require(self, exec_ctx):
)

if should_exit:
return RTResult().success_exit(Number.null())
return RTResult().success(Number.null())
return RTResult().success_exit(Null.null())
return RTResult().success(Null.null())

@args([])
def execute_exit(self, exec_ctx):
return RTResult().success_exit(Number.null())
return RTResult().success_exit(Null.null())

@args(["value"])
def execute_is_null(self, ctx):
value = ctx.symbol_table.get("value")

if isinstance(value, Null):
return RTResult().success(Boolean(True))
else:
return RTResult().success(Boolean(False))


def run(
Expand Down Expand Up @@ -470,7 +479,7 @@ def create_global_symbol_table() -> SymbolTable:
import core.builtin_classes as bic

ret = SymbolTable()
ret.set("null", Number.null())
ret.set("null", Null.null())
ret.set("false", Boolean.false())
ret.set("true", Boolean.true())
ret.set("print", BuiltInFunction("print"))
Expand All @@ -489,6 +498,7 @@ def create_global_symbol_table() -> SymbolTable:
ret.set("is_bool", BuiltInFunction("is_bool"))
ret.set("is_array", BuiltInFunction("is_array"))
ret.set("is_fun", BuiltInFunction("is_fun"))
ret.set("is_null", BuiltInFunction("is_null"))
# Internal array methods
ret.set("arr_append", BuiltInFunction("arr_append"))
ret.set("arr_pop", BuiltInFunction("arr_pop"))
Expand Down
37 changes: 30 additions & 7 deletions core/datatypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,10 +279,6 @@ def __str__(self) -> str:
def __repr__(self) -> str:
return str(self.value)

@classmethod
def null(cls) -> Number:
return cls(0)

@classmethod
def one(cls) -> Number:
return cls(1)
Expand Down Expand Up @@ -820,7 +816,7 @@ def _radonify(value: object) -> Value:
case False:
return Boolean.false()
case None:
return Number.null()
return Null.null()
case _ if inspect.isfunction(value):
from core.builtin_funcs import BuiltInFunction, args # Lazy import

Expand Down Expand Up @@ -924,7 +920,7 @@ def pyapi(self, ns: HashMap) -> RTResult[Value]:
self.context,
)
)
return RTResult[Value]().success(Number.null())
return RTResult[Value]().success(Null.null())

def copy(self) -> PyAPI:
copy = PyAPI(self.code)
Expand Down Expand Up @@ -1243,7 +1239,7 @@ def execute(self, args: list[Value], kwargs: dict[str, Value]) -> RTResult[Value
if res.should_return() and res.func_return_value is None:
return res

ret_value = (value if self.should_auto_return else None) or res.func_return_value or Number.null()
ret_value = (value if self.should_auto_return else None) or res.func_return_value or Null.null()
return res.success(ret_value)

def copy(self) -> Function:
Expand Down Expand Up @@ -1274,3 +1270,30 @@ def copy(self) -> Module:

def __repr__(self) -> str:
return f"<module {self.name} @ {self.file_path!r}>"


class Null(Value):
def __repr__(self) -> str:
return "null"

def copy(self) -> Null:
return self

def is_true(self) -> bool:
return False

def get_comparison_eq(self, other: Value) -> ResultTuple:
if isinstance(other, Null):
return Boolean.true(), None
else:
return Boolean.false(), None

def get_comparison_ne(self, other: Value) -> ResultTuple:
if isinstance(other, Null):
return Boolean.false(), None
else:
return Boolean.true(), None

@classmethod
def null(cls) -> Null:
return cls()
26 changes: 13 additions & 13 deletions core/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ def visit_IncludeNode(self, node: IncludeNode, context: Context) -> RTResult[Val
)

if should_exit:
return RTResult[Value]().success_exit(Number.null())
return RTResult[Value]().success_exit(Null.null())
assert isinstance(node.module.value, str), "this could be a bug in the parser"
module = Module(node.module.value, module_name, symbol_table)
res = RTResult[Value]()
Expand Down Expand Up @@ -277,17 +277,17 @@ def visit_IfNode(self, node: IfNode, context: Context) -> RTResult[Value]:
if res.should_return():
return res
assert expr_value is not None
return res.success(Number.null() if should_return_null else expr_value)
return res.success(Null.null() if should_return_null else expr_value)

if node.else_case is not None:
expr, should_return_null = node.else_case
expr_value = res.register(self.visit_block(expr, context))
if res.should_return():
return res
assert expr_value is not None
return res.success(Number.null() if should_return_null else expr_value)
return res.success(Null.null() if should_return_null else expr_value)

return res.success(Number.null())
return res.success(Null.null())

def visit_ForNode(self, node: ForNode, context: Context) -> RTResult[Value]:
res = RTResult[Value]()
Expand Down Expand Up @@ -363,7 +363,7 @@ def condition():
elements.append(value)

return res.success(
Number.null()
Null.null()
if node.should_return_null
else Array(elements).set_context(context).set_pos(node.pos_start, node.pos_end)
)
Expand Down Expand Up @@ -395,7 +395,7 @@ def visit_WhileNode(self, node: WhileNode, context: Context) -> RTResult[Value]:
elements.append(value)

return res.success(
Number.null()
Null.null()
if node.should_return_null
else Array(elements).set_context(context).set_pos(node.pos_start, node.pos_end)
)
Expand Down Expand Up @@ -473,7 +473,7 @@ def visit_ReturnNode(self, node: ReturnNode, context: Context) -> RTResult[Value
if res.should_return():
return res
else:
value = Number.null()
value = Null.null()
assert value is not None

return res.success_return(value)
Expand Down Expand Up @@ -502,9 +502,9 @@ def visit_TryNode(self, node: TryNode, context):
res.error.pos_start, res.error.pos_end, res.error.details, res.error.context, handled_error
)
)
return res.success(Number.null())
return res.success(Null.null())
else:
return res.success(Number.null())
return res.success(Null.null())

def visit_ForInNode(self, node: ForInNode, context: Context) -> RTResult[Value]:
res = RTResult[Value]()
Expand Down Expand Up @@ -536,7 +536,7 @@ def visit_ForInNode(self, node: ForInNode, context: Context) -> RTResult[Value]:
elements.append(element)

if should_return_null:
return res.success(Number.null())
return res.success(Null.null())
return res.success(Array(elements).set_context(context).set_pos(node.pos_start, node.pos_end))

def visit_SliceGetNode(self, node: SliceGetNode, context: Context) -> RTResult[Value]:
Expand Down Expand Up @@ -766,18 +766,18 @@ def visit_SwitchNode(self, node: SwitchNode, context: Context) -> RTResult[Value
if res.should_fallthrough:
should_continue = True
continue
return res.success(Number.null())
return res.success(Null.null())
should_continue = False

if node.default is not None:
res.register(self.visit(node.default, context))
if res.should_return():
return res
return res.success(Number.null())
return res.success(Null.null())
return res.failure(RTError(node.pos_start, node.subject_node.pos_end, "No cases matched", context))

def visit_FallthroughNode(self, node: FallthroughNode, context: Context) -> RTResult[Value]:
return RTResult[Value]().success(Number.null()).fallthrough()
return RTResult[Value]().success(Null.null()).fallthrough()

def visit_AttrAccessNode(self, node: AttrAccessNode, context: Context) -> RTResult[Value]:
res = RTResult[Value]()
Expand Down
2 changes: 1 addition & 1 deletion core/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -1528,7 +1528,7 @@ def success_exit(self, exit_value: T) -> RTResult[T]:

def fallthrough(self) -> RTResult[T]:
# No `self.reset()` because this is meant to be used in conjunction with other methods
# e.g. `res.success(Number.null()).fallthrough()`
# e.g. `res.success(Null.null()).fallthrough()`
self.should_fallthrough = True
return self

Expand Down
2 changes: 1 addition & 1 deletion examples/operator_overloading.rn
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class WrongOp {
}

fun dump(name = null) {
if name == null {
if is_null(name) {
print("WrongOp("+this.x+")")
} else {
print(name+" = WrongOp("+this.x+")")
Expand Down
2 changes: 1 addition & 1 deletion tests/closures.rn
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
fun make_var() {
val = null
return fun(new_val=null) {
if new_val == null {
if is_null(new_val) {
return val
} else {
nonlocal val = new_val
Expand Down
2 changes: 1 addition & 1 deletion tests/closures.rn.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"code": 0, "stdout": "0\n0\n69\n0\n69\n420\n", "stderr": ""}
{"code": 0, "stdout": "null\nnull\n69\nnull\n69\n420\n", "stderr": ""}

0 comments on commit f976787

Please sign in to comment.