mirror of
https://github.com/janet-lang/janet
synced 2024-11-16 05:34:48 +00:00
More work on frontend.
This commit is contained in:
parent
ef2dfcd7c3
commit
745567a2e0
@ -51,16 +51,18 @@
|
||||
(array/push into ~(type-prim ,name ,native-name))
|
||||
(make-type name))
|
||||
(add-prim-type 'float 'f32)
|
||||
(add-prim-type 'double 'f64))
|
||||
(add-prim-type 'double 'f64)
|
||||
(add-prim-type 'boolean 'boolean))
|
||||
|
||||
(defn type-extract
|
||||
"Given a symbol:type combination, extract the proper name and the type separately"
|
||||
[combined-name &opt default-type]
|
||||
(def parts (string/split ":" combined-name 0 1))
|
||||
(def parts (string/split ":" combined-name 0 2))
|
||||
(def [name tp] parts)
|
||||
[(symbol name) (symbol (or tp default-type))])
|
||||
|
||||
(var do-binop nil)
|
||||
(var do-comp nil)
|
||||
|
||||
(defn visit1
|
||||
"Take in a form and compile code and put it into `into`. Return result slot."
|
||||
@ -92,6 +94,14 @@
|
||||
'* (do-binop 'multiply args into)
|
||||
'/ (do-binop 'divide args into)
|
||||
|
||||
# Comparison
|
||||
'= (do-comp 'eq args into)
|
||||
'not= (do-comp 'neq args into)
|
||||
'< (do-comp 'lt args into)
|
||||
'<= (do-comp 'lte args into)
|
||||
'> (do-comp 'gt args into)
|
||||
'>= (do-comp 'gte args into)
|
||||
|
||||
# Type hinting
|
||||
'the
|
||||
(do
|
||||
@ -111,7 +121,8 @@
|
||||
(def [name tp] (type-extract full-name 'double))
|
||||
(def result (visit1 value into))
|
||||
(def slot (get-slot name))
|
||||
(array/push into ~(bind ,slot ,tp))
|
||||
(when tp
|
||||
(array/push into ~(bind ,slot ,tp)))
|
||||
(array/push into ~(move ,slot ,result))
|
||||
slot)
|
||||
|
||||
@ -146,6 +157,8 @@
|
||||
(errorf "cannot compile %V" code)))
|
||||
|
||||
(varfn do-binop
|
||||
"Emit a 'binary' op succh as (+ x y).
|
||||
Extended to support any number of arguments such as (+ x y z ...)"
|
||||
[opcode args into]
|
||||
(var final nil)
|
||||
(each arg args
|
||||
@ -161,14 +174,38 @@
|
||||
right)))
|
||||
(assert final))
|
||||
|
||||
(varfn do-comp
|
||||
"Emit a comparison form such as (= x y z ...)"
|
||||
[opcode args into]
|
||||
(def result (get-slot))
|
||||
(def needs-temp (> 2 (length args)))
|
||||
(def temp-result (if needs-temp (get-slot) nil))
|
||||
(array/push into ~(bind ,result boolean))
|
||||
(when needs-temp
|
||||
(array/push into ~(bind ,temp-result boolean)))
|
||||
(var left nil)
|
||||
(var first-compare true)
|
||||
(each arg args
|
||||
(def right (visit1 arg into))
|
||||
(when left
|
||||
(if first-compare
|
||||
(array/push into ~(,opcode ,result ,left ,right))
|
||||
(do
|
||||
(array/push into ~(,opcode ,temp-result ,left ,right))
|
||||
(array/push into ~(and ,result ,temp-result ,result))))
|
||||
(set first-compare false))
|
||||
(set left right))
|
||||
result)
|
||||
|
||||
###
|
||||
###
|
||||
###
|
||||
|
||||
(def myprog
|
||||
'(do
|
||||
(def xyz (+ 1 2 3))
|
||||
(def abc (* 4 5 6))
|
||||
(def xyz:double (+ 1 2 3))
|
||||
(def abc:double (* 4 5 6))
|
||||
(def x:boolean (= 5 7))
|
||||
(return (/ abc xyz))))
|
||||
|
||||
(defn dotest
|
||||
|
@ -132,7 +132,7 @@ static void janet_mark_many(const Janet *values, int32_t n) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Mark a bunch of key values items in memory */
|
||||
/* Mark only the keys from a sequence of key-value pairs */
|
||||
static void janet_mark_keys(const JanetKV *kvs, int32_t n) {
|
||||
const JanetKV *end = kvs + n;
|
||||
while (kvs < end) {
|
||||
@ -141,7 +141,7 @@ static void janet_mark_keys(const JanetKV *kvs, int32_t n) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Mark a bunch of key values items in memory */
|
||||
/* Mark only the values from a sequence of key-value pairs */
|
||||
static void janet_mark_values(const JanetKV *kvs, int32_t n) {
|
||||
const JanetKV *end = kvs + n;
|
||||
while (kvs < end) {
|
||||
@ -150,7 +150,7 @@ static void janet_mark_values(const JanetKV *kvs, int32_t n) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Mark a bunch of key values items in memory */
|
||||
/* Mark key-value pairs */
|
||||
static void janet_mark_kvs(const JanetKV *kvs, int32_t n) {
|
||||
const JanetKV *end = kvs + n;
|
||||
while (kvs < end) {
|
||||
|
@ -120,6 +120,18 @@ static void janet_net_socknoblock(JSock s) {
|
||||
#endif
|
||||
}
|
||||
|
||||
static void janet_net_nodelay(JanetStream *stream) {
|
||||
int flag = 1;
|
||||
setsockopt((JSock) stream->handle, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
|
||||
stream->flags |= JANET_STREAM_BUFFERED;
|
||||
}
|
||||
|
||||
static void janet_net_delay(JanetStream *stream) {
|
||||
int flag = 0;
|
||||
setsockopt((JSock) stream->handle, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
|
||||
stream->flags &= ~JANET_STREAM_BUFFERED;
|
||||
}
|
||||
|
||||
/* State machine for async connect */
|
||||
|
||||
void net_callback_connect(JanetFiber *fiber, JanetAsyncEvent event) {
|
||||
@ -953,6 +965,7 @@ struct sockopt_type {
|
||||
/* List of supported socket options; The type JANET_POINTER is used
|
||||
* for options that require special handling depending on the type. */
|
||||
static const struct sockopt_type sockopt_type_list[] = {
|
||||
{ "tcp-nodelay", IPPROTO_TCP, TCP_NODELAY, JANET_BOOLEAN },
|
||||
{ "so-broadcast", SOL_SOCKET, SO_BROADCAST, JANET_BOOLEAN },
|
||||
{ "so-reuseaddr", SOL_SOCKET, SO_REUSEADDR, JANET_BOOLEAN },
|
||||
{ "so-keepalive", SOL_SOCKET, SO_KEEPALIVE, JANET_BOOLEAN },
|
||||
@ -974,6 +987,7 @@ JANET_CORE_FN(cfun_net_setsockopt,
|
||||
"- :so-broadcast boolean\n"
|
||||
"- :so-reuseaddr boolean\n"
|
||||
"- :so-keepalive boolean\n"
|
||||
"- :tcp-nodelay boolean\n"
|
||||
"- :ip-multicast-ttl number\n"
|
||||
"- :ip-add-membership string\n"
|
||||
"- :ip-drop-membership string\n"
|
||||
|
108
src/core/sysir.c
108
src/core/sysir.c
@ -31,7 +31,6 @@
|
||||
* [x] named registers and types
|
||||
* [x] better type errors (perhaps mostly for compiler debugging - full type system goes on top)
|
||||
* [ ] switch internal use of uint32_t everywhere to type struct wrappers for safety
|
||||
* [ ] support for switch-case
|
||||
* [ ] x86/x64 machine code target
|
||||
* [ ] LLVM target
|
||||
* [ ] target specific extensions - custom instructions and custom primitives
|
||||
@ -1075,9 +1074,112 @@ static JanetString rname(JanetSysIR *sysir, uint32_t regid) {
|
||||
return name;
|
||||
}
|
||||
|
||||
static int reg_is_unknown_type(JanetSysIR *sysir, uint32_t reg) {
|
||||
JanetSysIRLinkage *linkage = sysir->linkage;
|
||||
uint32_t t = sysir->types[reg];
|
||||
return (linkage->type_defs[t].prim == JANET_PRIM_UNKNOWN);
|
||||
}
|
||||
|
||||
static void janet_sysir_type_check(JanetSysIR *sysir) {
|
||||
|
||||
/* TODO: Simple forward type inference */
|
||||
/* Simple forward type inference */
|
||||
for (uint32_t i = 0; i < sysir->instruction_count; i++) {
|
||||
JanetSysInstruction instruction = sysir->instructions[i];
|
||||
switch (instruction.opcode) {
|
||||
default:
|
||||
break;
|
||||
case JANET_SYSOP_MOVE:
|
||||
if (reg_is_unknown_type(sysir, instruction.two.dest)) {
|
||||
sysir->types[instruction.two.dest] = sysir->types[instruction.two.src];
|
||||
}
|
||||
if (reg_is_unknown_type(sysir, instruction.two.src)) {
|
||||
sysir->types[instruction.two.src] = sysir->types[instruction.two.dest];
|
||||
}
|
||||
break;
|
||||
case JANET_SYSOP_CAST:
|
||||
tcheck_cast(sysir, instruction.two.dest, instruction.two.src);
|
||||
break;
|
||||
case JANET_SYSOP_POINTER_ADD:
|
||||
case JANET_SYSOP_POINTER_SUBTRACT:
|
||||
tcheck_pointer_math(sysir, instruction.three.dest, instruction.three.lhs, instruction.three.rhs);
|
||||
break;
|
||||
case JANET_SYSOP_ADD:
|
||||
case JANET_SYSOP_SUBTRACT:
|
||||
case JANET_SYSOP_MULTIPLY:
|
||||
case JANET_SYSOP_DIVIDE:
|
||||
tcheck_number(sysir, tcheck_array_element(sysir, sysir->types[instruction.three.dest]));
|
||||
tcheck_equal(sysir, instruction.three.lhs, instruction.three.rhs);
|
||||
tcheck_equal(sysir, instruction.three.dest, instruction.three.lhs);
|
||||
break;
|
||||
case JANET_SYSOP_BAND:
|
||||
case JANET_SYSOP_BOR:
|
||||
case JANET_SYSOP_BXOR:
|
||||
tcheck_integer(sysir, tcheck_array_element(sysir, sysir->types[instruction.three.dest]));
|
||||
tcheck_equal(sysir, instruction.three.lhs, instruction.three.rhs);
|
||||
tcheck_equal(sysir, instruction.three.dest, instruction.three.lhs);
|
||||
break;
|
||||
case JANET_SYSOP_BNOT:
|
||||
tcheck_integer(sysir, tcheck_array_element(sysir, sysir->types[instruction.two.src]));
|
||||
tcheck_equal(sysir, instruction.two.dest, instruction.two.src);
|
||||
break;
|
||||
case JANET_SYSOP_SHL:
|
||||
case JANET_SYSOP_SHR:
|
||||
tcheck_integer(sysir, tcheck_array_element(sysir, sysir->types[instruction.three.lhs]));
|
||||
tcheck_equal(sysir, instruction.three.lhs, instruction.three.rhs);
|
||||
tcheck_equal(sysir, instruction.three.dest, instruction.three.lhs);
|
||||
break;
|
||||
case JANET_SYSOP_LOAD:
|
||||
tcheck_pointer_equals(sysir, instruction.two.src, instruction.two.dest);
|
||||
break;
|
||||
case JANET_SYSOP_STORE:
|
||||
tcheck_pointer_equals(sysir, instruction.two.dest, instruction.two.src);
|
||||
break;
|
||||
case JANET_SYSOP_GT:
|
||||
case JANET_SYSOP_LT:
|
||||
case JANET_SYSOP_EQ:
|
||||
case JANET_SYSOP_NEQ:
|
||||
case JANET_SYSOP_GTE:
|
||||
case JANET_SYSOP_LTE:
|
||||
/* TODO - allow arrays */
|
||||
tcheck_number_or_pointer(sysir, sysir->types[instruction.three.lhs]);
|
||||
tcheck_equal(sysir, instruction.three.lhs, instruction.three.rhs);
|
||||
//tcheck_equal(sysir, instruction.three.dest, instruction.three.lhs);
|
||||
tcheck_boolean(sysir, sysir->types[instruction.three.dest]);
|
||||
break;
|
||||
case JANET_SYSOP_ADDRESS:
|
||||
tcheck_pointer(sysir, sysir->types[instruction.two.dest]);
|
||||
break;
|
||||
case JANET_SYSOP_BRANCH:
|
||||
tcheck_boolean(sysir, sysir->types[instruction.branch.cond]);
|
||||
if (instruction.branch.to >= sysir->instruction_count) {
|
||||
janet_panicf("label outside of range [0, %u), got %u", sysir->instruction_count, instruction.branch.to);
|
||||
}
|
||||
break;
|
||||
case JANET_SYSOP_CONSTANT:
|
||||
tcheck_constant(sysir, instruction.constant.dest, sysir->constants[instruction.constant.constant]);
|
||||
break;
|
||||
case JANET_SYSOP_CALL:
|
||||
tcheck_pointer(sysir, sysir->types[instruction.call.callee]);
|
||||
break;
|
||||
case JANET_SYSOP_ARRAY_GETP:
|
||||
tcheck_array_getp(sysir, instruction.three.dest, instruction.three.lhs, instruction.three.lhs);
|
||||
break;
|
||||
case JANET_SYSOP_ARRAY_PGETP:
|
||||
tcheck_array_pgetp(sysir, instruction.three.dest, instruction.three.lhs, instruction.three.lhs);
|
||||
break;
|
||||
case JANET_SYSOP_FIELD_GETP:
|
||||
tcheck_fgetp(sysir, instruction.field.r, instruction.field.st, instruction.field.field);
|
||||
break;
|
||||
case JANET_SYSOP_CALLK:
|
||||
/* TODO - check function return type */
|
||||
break;
|
||||
}
|
||||
/* Write back possibly modified instruction */
|
||||
sysir->instructions[i] = instruction;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Assert no unknown types */
|
||||
JanetSysIRLinkage *linkage = sysir->linkage;
|
||||
@ -1173,7 +1275,7 @@ static void janet_sysir_type_check(JanetSysIR *sysir) {
|
||||
/* TODO - allow arrays */
|
||||
tcheck_number_or_pointer(sysir, sysir->types[instruction.three.lhs]);
|
||||
tcheck_equal(sysir, instruction.three.lhs, instruction.three.rhs);
|
||||
tcheck_equal(sysir, instruction.three.dest, instruction.three.lhs);
|
||||
//tcheck_equal(sysir, instruction.three.dest, instruction.three.lhs);
|
||||
tcheck_boolean(sysir, sysir->types[instruction.three.dest]);
|
||||
break;
|
||||
case JANET_SYSOP_ADDRESS:
|
||||
|
@ -584,6 +584,7 @@ typedef void *JanetAbstract;
|
||||
#define JANET_STREAM_WRITABLE 0x400
|
||||
#define JANET_STREAM_ACCEPTABLE 0x800
|
||||
#define JANET_STREAM_UDPSERVER 0x1000
|
||||
#define JANET_STREAM_BUFFERED 0x2000
|
||||
#define JANET_STREAM_TOCLOSE 0x10000
|
||||
|
||||
typedef enum {
|
||||
|
Loading…
Reference in New Issue
Block a user