Added typeof opcode to verify variable types.
This commit is contained in:
parent
d7843274ee
commit
7e9f24114e
6 changed files with 78 additions and 1 deletions
50
examples/typeof.fun
Executable file
50
examples/typeof.fun
Executable file
|
|
@ -0,0 +1,50 @@
|
|||
#!/usr/bin/env fun
|
||||
|
||||
/*
|
||||
* This file is part of the Fun programming language.
|
||||
* https://hanez.org/project/fun/
|
||||
*
|
||||
* Copyright 2025 Johannes Findeisen <you@hanez.org>
|
||||
* Licensed under the terms of the ISC license.
|
||||
* https://opensource.org/license/isc-license-txt
|
||||
*/
|
||||
|
||||
print("=== Typeof test start ===")
|
||||
|
||||
// Array
|
||||
a = [1, 2, 3]
|
||||
print(typeof(a))
|
||||
|
||||
fun f()
|
||||
print("A function!")
|
||||
|
||||
// Function
|
||||
print(typeof(f))
|
||||
f()
|
||||
|
||||
// Map
|
||||
m = { "x": 1, "y": 2, "move": move }
|
||||
print(typeof(m))
|
||||
|
||||
// Nil
|
||||
nil x = nil
|
||||
print(typeof(x))
|
||||
|
||||
// Number
|
||||
number n = 10
|
||||
print(typeof(n))
|
||||
|
||||
string s = "Have fun!"
|
||||
print(typeof(s))
|
||||
|
||||
print("=== Typeof test end ===")
|
||||
|
||||
/* Expected output:
|
||||
Array
|
||||
Function
|
||||
A function!
|
||||
Map
|
||||
Nil
|
||||
Number
|
||||
String
|
||||
*/
|
||||
|
|
@ -72,6 +72,7 @@ typedef enum {
|
|||
// conversions
|
||||
OP_TO_NUMBER, // pops any; pushes int (parse strings)
|
||||
OP_TO_STRING, // pops any; pushes string
|
||||
OP_TYPEOF, // pops any; pushes string name of type
|
||||
|
||||
// string ops
|
||||
OP_SPLIT, // pops sep, string; pushes array of strings
|
||||
|
|
|
|||
|
|
@ -448,6 +448,14 @@ static int emit_primary(Bytecode *bc, const char *src, size_t len, size_t *pos)
|
|||
free(name);
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(name, "typeof") == 0) {
|
||||
(*pos)++; /* '(' */
|
||||
if (!emit_expression(bc, src, len, pos)) { parser_fail(*pos, "typeof expects 1 argument"); free(name); return 0; }
|
||||
if (!consume_char(src, len, pos, ')')) { parser_fail(*pos, "Expected ')' after typeof arg"); free(name); return 0; }
|
||||
bytecode_add_instruction(bc, OP_TYPEOF, 0);
|
||||
free(name);
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(name, "keys") == 0) {
|
||||
(*pos)++; /* '(' */
|
||||
if (!emit_expression(bc, src, len, pos) || !consume_char(src, len, pos, ')')) { parser_fail(*pos, "keys expects 1 arg"); free(name); return 0; }
|
||||
|
|
|
|||
1
src/vm.c
1
src/vm.c
|
|
@ -273,6 +273,7 @@ void vm_run(VM *vm, Bytecode *entry) {
|
|||
#include "vm/print.c"
|
||||
#include "vm/to_number.c"
|
||||
#include "vm/to_string.c"
|
||||
#include "vm/typeof.c"
|
||||
|
||||
default:
|
||||
if (!opcode_is_valid(inst.op)) {
|
||||
|
|
|
|||
2
src/vm.h
2
src/vm.h
|
|
@ -35,7 +35,7 @@ static const char *opcode_names[] = {
|
|||
"MOD","AND","OR","NOT","DUP","SWAP",
|
||||
"MAKE_ARRAY","INDEX_GET","INDEX_SET",
|
||||
"LEN","ARR_PUSH","ARR_POP","ARR_SET","ARR_INSERT","ARR_REMOVE","SLICE",
|
||||
"TO_NUMBER","TO_STRING",
|
||||
"TO_NUMBER","TO_STRING","TYPEOF",
|
||||
"SPLIT","JOIN","SUBSTR","FIND",
|
||||
"CONTAINS","INDEX_OF","CLEAR",
|
||||
"ENUMERATE","ZIP",
|
||||
|
|
|
|||
17
src/vm/typeof.c
Normal file
17
src/vm/typeof.c
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
case OP_TYPEOF: {
|
||||
Value v = pop_value(vm);
|
||||
const char *tname = "Unknown";
|
||||
switch (v.type) {
|
||||
case VAL_INT: tname = "Number"; break;
|
||||
case VAL_STRING: tname = "String"; break;
|
||||
case VAL_FUNCTION: tname = "Function"; break;
|
||||
case VAL_ARRAY: tname = "Array"; break;
|
||||
case VAL_MAP: tname = "Map"; break;
|
||||
case VAL_NIL: tname = "Nil"; break;
|
||||
default: tname = "Unknown"; break;
|
||||
}
|
||||
/* push a new string value; make_string duplicates the C string */
|
||||
push_value(vm, make_string(tname));
|
||||
free_value(v);
|
||||
break;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue