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
|
// conversions
|
||||||
OP_TO_NUMBER, // pops any; pushes int (parse strings)
|
OP_TO_NUMBER, // pops any; pushes int (parse strings)
|
||||||
OP_TO_STRING, // pops any; pushes string
|
OP_TO_STRING, // pops any; pushes string
|
||||||
|
OP_TYPEOF, // pops any; pushes string name of type
|
||||||
|
|
||||||
// string ops
|
// string ops
|
||||||
OP_SPLIT, // pops sep, string; pushes array of strings
|
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);
|
free(name);
|
||||||
return 1;
|
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) {
|
if (strcmp(name, "keys") == 0) {
|
||||||
(*pos)++; /* '(' */
|
(*pos)++; /* '(' */
|
||||||
if (!emit_expression(bc, src, len, pos) || !consume_char(src, len, pos, ')')) { parser_fail(*pos, "keys expects 1 arg"); free(name); return 0; }
|
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/print.c"
|
||||||
#include "vm/to_number.c"
|
#include "vm/to_number.c"
|
||||||
#include "vm/to_string.c"
|
#include "vm/to_string.c"
|
||||||
|
#include "vm/typeof.c"
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (!opcode_is_valid(inst.op)) {
|
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",
|
"MOD","AND","OR","NOT","DUP","SWAP",
|
||||||
"MAKE_ARRAY","INDEX_GET","INDEX_SET",
|
"MAKE_ARRAY","INDEX_GET","INDEX_SET",
|
||||||
"LEN","ARR_PUSH","ARR_POP","ARR_SET","ARR_INSERT","ARR_REMOVE","SLICE",
|
"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",
|
"SPLIT","JOIN","SUBSTR","FIND",
|
||||||
"CONTAINS","INDEX_OF","CLEAR",
|
"CONTAINS","INDEX_OF","CLEAR",
|
||||||
"ENUMERATE","ZIP",
|
"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