1
0
mirror of https://github.com/janet-lang/janet synced 2025-01-05 05:10:26 +00:00

Better printing for complex constants.

Also added stub for checking if constants are valid in IR, but it is
not currently used.
This commit is contained in:
Calvin Rose 2024-09-30 08:14:01 -05:00
parent 731592a80e
commit 6577a18cef
3 changed files with 97 additions and 9 deletions

View File

@ -11,6 +11,7 @@
(def name-to-type @{})
(def slot-types @{})
(def functions @{})
(def type-fields @{})
(defn get-slot
[&opt new-name]
@ -105,6 +106,12 @@
(symbol? code)
(named-slot code)
# Array literals
(and (tuple? code) (= :brackets (tuple/type code)))
(do
(assert type-hint (string/format "unknown type for array literal %v" code))
~(,type-hint ,code))
# Compile forms
(and (tuple? code) (= :parens (tuple/type code)))
(do

View File

@ -11,6 +11,7 @@
c long)
(defarray myvec float 4)
(defarray mymat myvec 4)
(defn-external printf:int [fmt:pointer x:int]) # TODO varargs
@ -38,7 +39,7 @@
(defsys doloop [x:int y:int]
(var i:int x)
(while (< i y)
(set i (the int (+ 1 i)))
(set i (+ 1 i))
(printf "i = %d\n" i))
(myprog)
(return x))
@ -57,9 +58,13 @@
(return (+ a b)))
(defsys make_array:myvec []
(def vec:myvec 0)
(def vec:myvec [0 0 0 0])
(return vec))
(defsys make_mat:mymat []
(def mat:mymat [[1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1]])
(return mat))
####
#(dump)

View File

@ -315,6 +315,7 @@ static uint32_t instr_read_operand_or_const(Janet x, JanetSysIR *ir) {
Janet c = tup[1];
jsc.type = instr_read_type_operand(tup[0], ir, READ_TYPE_REFERENCE);
jsc.value = c;
/* TODO - Use a hash table or something better than linear lookup */
for (int32_t i = 0; i < janet_v_count(ir->constants); i++) {
if (ir->constants[i].type != jsc.type) continue;
if (!janet_equals(ir->constants[i].value, c)) continue;
@ -1047,6 +1048,63 @@ static JanetString rname(JanetSysIR *sysir, uint32_t regid) {
return name;
}
/* Check if a constant value is compatible with a type.
* - Janet numbers are compatible with all numeric types (if in range)
* - Booleans are compatible with booleans
* - Signed integers are compatible with all integer types (if in range)
* - Strings and Pointers are compatible with pointers.
* - Tuples of the correct length are compatible with array types if all elements are compatible with the element type
* - TODO - structs and tables */
static int check_const_valid(JanetSysIR *sysir, Janet constant, uint32_t t) {
JanetSysIRLinkage *linkage = sysir->linkage;
JanetSysTypeInfo *tinfo = &linkage->type_defs[t];
JanetPrim p = tinfo->prim;
switch (janet_type(constant)) {
default:
return 0;
case JANET_TUPLE:
{
const Janet *elements = janet_unwrap_tuple(constant);
int32_t len = janet_tuple_length(elements);
if (p != JANET_PRIM_ARRAY) return 0;
if ((uint64_t) len != tinfo->array.fixed_count) return 0;
for (int32_t i = 0; i < len; i++) {
if (!check_const_valid(sysir, elements[i], tinfo->array.type)) return 0;
}
return 1;
}
case JANET_BOOLEAN:
return p == JANET_PRIM_BOOLEAN;
case JANET_STRING:
case JANET_POINTER:
return p == JANET_PRIM_POINTER;
case JANET_NUMBER:
{
double x = janet_unwrap_number(constant);
if (p == JANET_PRIM_F64) return 1;
if (p == JANET_PRIM_F32) return 1;
if (x != floor(x)) return 0; /* Filter out non-integers */
if (p == JANET_PRIM_U8 && (x >= 0 && x <= UINT8_MAX)) return 1;
if (p == JANET_PRIM_S8 && (x >= INT8_MIN && x <= INT8_MAX)) return 1;
if (p == JANET_PRIM_U16 && (x >= 0 && x <= UINT16_MAX)) return 1;
if (p == JANET_PRIM_S16 && (x >= INT16_MIN && x <= INT16_MAX)) return 1;
if (p == JANET_PRIM_U32 && (x >= 0 && x <= UINT32_MAX)) return 1;
if (p == JANET_PRIM_S32 && (x >= INT32_MIN && x <= INT32_MAX)) return 1;
if (p == JANET_PRIM_U64 && (x >= 0 && x <= UINT64_MAX)) return 1;
if (p == JANET_PRIM_S64 && (x >= INT64_MIN && x <= INT64_MAX)) return 1;
return 0;
}
case JANET_ABSTRACT:
{
void *point = janet_unwrap_abstract(constant);
const JanetAbstractType *at = janet_abstract_type(point);
if (at == &janet_s64_type && p == JANET_PRIM_S64) return 1;
if (at == &janet_u64_type && p == JANET_PRIM_U64) return 1;
return 0;
}
}
}
static void janet_sysir_type_check(JanetSysIR *sysir) {
/* Assert no unknown types */
@ -1251,17 +1309,35 @@ static const char *c_prim_names[] = {
"bool"
};
/* Print a C constant */
static void print_const_c(JanetSysIR *ir, JanetBuffer *buf, Janet c, uint32_t tid) {
/* JanetSysTypeInfo *tinfo = &ir->linkage->type_defs[tid]; */
if (janet_checktype(c, JANET_TUPLE)) {
const Janet *elements = janet_unwrap_tuple(c);
janet_formatb(buf, "((_t%d){", tid);
for (int32_t i = 0; i < janet_tuple_length(elements); i++) {
if (i > 0) janet_formatb(buf, ", ");
/* TODO - limit recursion? */
uint32_t sub_type = ir->linkage->type_defs[tid].array.type;
print_const_c(ir, buf, elements[i], sub_type);
}
janet_formatb(buf, "})");
} else if (janet_checktype(c, JANET_ABSTRACT)) {
/* Allow printing int types */
janet_formatb(buf, "%V", c);
} else {
janet_formatb(buf, "%v", c);
}
}
static void op_or_const(JanetSysIR *ir, JanetBuffer *buf, uint32_t reg) {
if (reg < JANET_SYS_MAX_OPERAND) {
janet_formatb(buf, "_r%u", reg);
} else {
uint32_t constant_id = reg - JANET_SYS_CONSTANT_PREFIX;
if (janet_checktype(ir->constants[constant_id].value, JANET_ABSTRACT)) {
/* Allow printing int types */
janet_formatb(buf, "%V", ir->constants[constant_id].value);
} else {
janet_formatb(buf, "%v", ir->constants[constant_id].value);
}
uint32_t tid = ir->constants[constant_id].type;
Janet c = ir->constants[constant_id].value;
print_const_c(ir, buf, c, tid);
}
}
@ -1322,7 +1398,7 @@ void janet_sys_ir_lower_to_c(JanetSysIRLinkage *linkage, JanetBuffer *buffer) {
#define EMITBINOP(OP) emit_binop(ir, buffer, tempbuf, instruction, OP)
/* Prelude */
janet_formatb(buffer, "#include <stddef.h>\n#include <stdint.h>\n#include <stdbool.h>\n#include <stdio.h>\n#include <sys/syscall.h>\n\n");
janet_formatb(buffer, "#include <stddef.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <stdbool.h>\n#include <stdio.h>\n#include <sys/syscall.h>\n#define _t0 void\n\n");
/* Emit type defs */
for (uint32_t j = 0; j < (uint32_t) linkage->ir_ordered->count; j++) {