mirror of
https://github.com/janet-lang/janet
synced 2025-01-07 22:20:26 +00:00
Begin working on drawing example.
This commit is contained in:
parent
b096babcbf
commit
bc79489068
79
examples/sysir/drawing.janet
Normal file
79
examples/sysir/drawing.janet
Normal file
@ -0,0 +1,79 @@
|
||||
###
|
||||
### Create a .bmp file on linux.
|
||||
###
|
||||
|
||||
(use ./frontend)
|
||||
|
||||
(defpointer p32 uint)
|
||||
(defn-external write:void [fd:int mem:pointer size:uint])
|
||||
(defn-external exit:void [x:int])
|
||||
(defn-external malloc:p32 [x:uint])
|
||||
(defn-external free:void [m:p32])
|
||||
|
||||
# assume 128x128 32 bit color image
|
||||
# Size : 128 * 128 * 4 + align(14 + 40, 4) = 65592
|
||||
# dib offset : align(14 + 40, 4) = 56
|
||||
|
||||
(setdyn :verbose true)
|
||||
|
||||
|
||||
(defsys write_32:void [x:uint]
|
||||
(write 1 (address x) 4)
|
||||
(return))
|
||||
|
||||
(defsys write_16:void [x:uint]
|
||||
(write 1 (address x) 2)
|
||||
(return))
|
||||
|
||||
(defsys write_header:void [w:uint h:uint]
|
||||
(write 1 "BM" 2)
|
||||
(def size:uint (+ 56 (* w h 4)))
|
||||
(write_32 size)
|
||||
(write_32 0)
|
||||
(write_32 56) # pixel array offset
|
||||
# Begin DIB
|
||||
(write_32 40) # dib size
|
||||
(write_32 w)
|
||||
(write_32 h)
|
||||
(write_16 1) # color panes - must be 1
|
||||
(write_16 32) # bits per pixel
|
||||
(write_32 0) # compression method - no compression
|
||||
(write_32 0) # image size - not needed when no compression, 0 should be fine
|
||||
(write_32 8192) # pixels per meter - horizontal resolution
|
||||
(write_32 8192) # pixels per meter - vertical resolution
|
||||
(write_32 0) # number of colors in palette - no palette so 0
|
||||
(write_32 0) # number of "important colors" ignored in practice
|
||||
(write_16 0) # add "gap 1" to align pixel array to multiple of 4 bytes
|
||||
(return))
|
||||
|
||||
(defsys draw:void [w:uint h:uint]
|
||||
(def red:uint 0xFFFF0000)
|
||||
(def blue:uint 0xFF0000FF)
|
||||
(def size:uint (* w h 4))
|
||||
(def mem:p32 (malloc size))
|
||||
(store mem (the uint 10))
|
||||
(var y:uint 0)
|
||||
(while (< y h)
|
||||
(var x:uint 0)
|
||||
(while (< x w)
|
||||
#(write_32 (if (< y 32) blue red))
|
||||
(if (> y 64)
|
||||
(write_32 blue)
|
||||
(write_32 red))
|
||||
(set x (+ 1 x)))
|
||||
(set y (+ y 1)))
|
||||
(return))
|
||||
|
||||
(defsys main:int []
|
||||
(def w:uint 128)
|
||||
(def h:uint 128)
|
||||
(write_header w h)
|
||||
(draw w h)
|
||||
(return 0))
|
||||
|
||||
####
|
||||
|
||||
#(dump)
|
||||
(print "#include <unistd.h>")
|
||||
(dumpc)
|
||||
#(dumpx64)
|
@ -12,6 +12,7 @@
|
||||
(def slot-types @{})
|
||||
(def functions @{})
|
||||
(def type-fields @{})
|
||||
(def pointer-derefs @{})
|
||||
|
||||
(defn get-slot
|
||||
[&opt new-name]
|
||||
@ -65,11 +66,14 @@
|
||||
(add-prim-type 'float 'f32)
|
||||
(add-prim-type 'double 'f64)
|
||||
(add-prim-type 'int 's32)
|
||||
(add-prim-type 'uint 'u32)
|
||||
(add-prim-type 'long 's64)
|
||||
(add-prim-type 'ulong 'u64)
|
||||
(add-prim-type 'pointer 'pointer)
|
||||
(add-prim-type 'boolean 'boolean)
|
||||
(add-prim-type 's16 's16)
|
||||
(add-prim-type 'byte 'u8)
|
||||
(array/push into ~(type-pointer pointer byte))
|
||||
(make-type 'pointer)
|
||||
(sysir/asm ctx into)
|
||||
ctx)
|
||||
|
||||
@ -177,6 +181,41 @@
|
||||
(array/push into ~(move ,slot ,result))
|
||||
slot)
|
||||
|
||||
# Address of (& operator in C)
|
||||
'address
|
||||
(do
|
||||
(assert (= 1 (length args)))
|
||||
(def [thing] args)
|
||||
(def [name tp] (type-extract thing 'int))
|
||||
(def result (visit1 thing into false tp))
|
||||
(def slot (get-slot))
|
||||
#(assign-type name 'pointer)
|
||||
(array/push into ~(bind ,slot pointer))
|
||||
(array/push into ~(address ,slot ,result))
|
||||
slot)
|
||||
|
||||
'load
|
||||
(do
|
||||
(assert (= 1 (length args)))
|
||||
(def [thing] args)
|
||||
(def [name tp] (type-extract thing 'pointer))
|
||||
(def result (visit1 thing into false tp))
|
||||
(def slot (get-slot))
|
||||
(def ptype (or type-hint 'char))
|
||||
(array/push into ~(bind ,slot ,ptype))
|
||||
(array/push into ~(load ,slot ,result))
|
||||
slot)
|
||||
|
||||
'store
|
||||
(do
|
||||
(assert (= 2 (length args)))
|
||||
(def [dest value] args)
|
||||
(def [name tp] (type-extract dest 'pointer))
|
||||
(def dest-r (visit1 dest into false tp))
|
||||
(def value-r (visit1 value into false))
|
||||
(array/push into ~(store ,dest-r ,value-r))
|
||||
value-r)
|
||||
|
||||
# Assignment
|
||||
'set
|
||||
(do
|
||||
@ -229,15 +268,19 @@
|
||||
(assert (< 2 (length args) 4))
|
||||
(def [cnd tru fal] args)
|
||||
(def condition-slot (visit1 cnd into false 'boolean))
|
||||
(def ret (get-slot))
|
||||
(array/push into ~(bind ,ret ,type-hint))
|
||||
(def ret (if type-hint (get-slot)))
|
||||
(when type-hint (array/push into ~(bind ,ret ,type-hint)))
|
||||
(array/push into ~(branch ,condition-slot ,lab))
|
||||
# false path
|
||||
(array/push into ~(move ,ret ,(visit1 tru into false type-hint)))
|
||||
(if type-hint
|
||||
(array/push into ~(move ,ret ,(visit1 fal into false type-hint)))
|
||||
(visit1 fal into true))
|
||||
(array/push into ~(jump ,lab-end))
|
||||
(array/push into lab)
|
||||
# true path
|
||||
(array/push into ~(move ,ret ,(visit1 fal into false type-hint)))
|
||||
(if type-hint
|
||||
(array/push into ~(move ,ret ,(visit1 tru into false type-hint)))
|
||||
(visit1 tru into true))
|
||||
(array/push into lab-end)
|
||||
ret)
|
||||
|
||||
@ -376,6 +419,16 @@
|
||||
# (eprintf "%.99M" into)
|
||||
(sysir/asm ctx into))
|
||||
|
||||
# Declare a pointer type
|
||||
'defpointer
|
||||
(do
|
||||
(def into @[])
|
||||
(def [name element] rest)
|
||||
(def field-types @[])
|
||||
(array/push into ~(type-pointer ,name ,element))
|
||||
# (eprintf "%.99M" into)
|
||||
(sysir/asm ctx into))
|
||||
|
||||
# Declare an array type
|
||||
'defarray
|
||||
(do
|
||||
@ -424,7 +477,7 @@
|
||||
(each part body
|
||||
(visit1 part ir-asm true)))
|
||||
(put functions fn-name (freeze signature))
|
||||
# (eprintf "%.99M" ir-asm)
|
||||
(when (dyn :verbose) (eprintf "%.99M" ir-asm))
|
||||
(sysir/asm ctx ir-asm))
|
||||
|
||||
(errorf "unknown form %p" form)))
|
||||
@ -463,5 +516,6 @@
|
||||
(defmacro defstruct [& args] [compile1 ~',(keep-syntax! (dyn *macro-form*) ~(defstruct ,;args))])
|
||||
(defmacro defunion [& args] [compile1 ~',(keep-syntax! (dyn *macro-form*) ~(defunion ,;args))])
|
||||
(defmacro defarray [& args] [compile1 ~',(keep-syntax! (dyn *macro-form*) ~(defarray ,;args))])
|
||||
(defmacro defpointer [& args] [compile1 ~',(keep-syntax! (dyn *macro-form*) ~(defpointer ,;args))])
|
||||
(defmacro defn-external [& args] [compile1 ~',(keep-syntax! (dyn *macro-form*) ~(defn-external ,;args))])
|
||||
(defmacro defsys [& args] [compile1 ~',(keep-syntax! (dyn *macro-form*) ~(defn ,;args))])
|
||||
|
5
examples/sysir/run_drawing.sh
Executable file
5
examples/sysir/run_drawing.sh
Executable file
@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
valgrind build/janet examples/sysir/drawing.janet > temp.nasm
|
||||
nasm -felf64 temp.nasm -l temp.lst -o temp.o
|
||||
ld -o temp.bin -dynamic-linker /lib64/ld-linux-x86-64.so.2 -lc temp.o
|
||||
valgrind ./temp.bin
|
@ -67,6 +67,6 @@
|
||||
|
||||
####
|
||||
|
||||
(dump)
|
||||
#(dump)
|
||||
#(dumpc)
|
||||
#(dumpx64)
|
||||
(dumpx64)
|
||||
|
@ -97,9 +97,9 @@ const char *janet_sysop_names[] = {
|
||||
"return", /* JANET_SYSOP_RETURN */
|
||||
"jump", /* JANET_SYSOP_JUMP */
|
||||
"branch", /* JANET_SYSOP_BRANCH */
|
||||
"branch_not", /* JANET_SYSOP_BRANCH_NOT */
|
||||
"branch-not", /* JANET_SYSOP_BRANCH_NOT */
|
||||
"address", /* JANET_SYSOP_ADDRESS */
|
||||
"type-primitive", /* JANET_SYSOP_TYPE_PRIMITIVE */
|
||||
"type-prim", /* JANET_SYSOP_TYPE_PRIMITIVE */
|
||||
"type-struct", /* JANET_SYSOP_TYPE_STRUCT */
|
||||
"type-bind", /* JANET_SYSOP_TYPE_BIND */
|
||||
"arg", /* JANET_SYSOP_ARG */
|
||||
@ -553,6 +553,13 @@ static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instruction
|
||||
instr_assert_length(tuple, 3, opvalue);
|
||||
instruction.type_prim.dest_type = instr_read_type_operand(tuple[1], out, READ_TYPE_DEFINITION);
|
||||
instruction.type_prim.prim = instr_read_prim(tuple[2]);
|
||||
if (instruction.type_prim.prim == JANET_PRIM_UNKNOWN ||
|
||||
instruction.type_prim.prim == JANET_PRIM_STRUCT ||
|
||||
instruction.type_prim.prim == JANET_PRIM_UNION ||
|
||||
instruction.type_prim.prim == JANET_PRIM_POINTER ||
|
||||
instruction.type_prim.prim == JANET_PRIM_ARRAY) {
|
||||
janet_panic("bad primitive");
|
||||
}
|
||||
janet_v_push(ir, instruction);
|
||||
break;
|
||||
}
|
||||
@ -1129,7 +1136,7 @@ static void janet_sysir_type_check(JanetSysIR *sysir) {
|
||||
JanetSysTypeInfo tinfo = linkage->type_defs[type];
|
||||
sysir->error_ctx = janet_wrap_number(i);
|
||||
if (tinfo.prim == JANET_PRIM_UNKNOWN) {
|
||||
janet_panicf("in %p, unable to infer type for %s", sysir->error_ctx, rname(sysir, i));
|
||||
janet_panicf("unable to infer type for %s (type %p), %d", rname(sysir, i), tname(sysir, type), type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1155,7 +1162,7 @@ static void janet_sysir_type_check(JanetSysIR *sysir) {
|
||||
uint32_t ret_type = 0;
|
||||
if (instruction.ret.has_value) {
|
||||
rcheck_const_valid(sysir, instruction.ret.value);
|
||||
ret_type = sysir->types[instruction.ret.value];
|
||||
ret_type = janet_sys_optype(sysir, instruction.ret.value);
|
||||
}
|
||||
if (found_return) {
|
||||
if (instruction.ret.has_value && !sysir->has_return_type) {
|
||||
@ -1246,7 +1253,7 @@ static void janet_sysir_type_check(JanetSysIR *sysir) {
|
||||
tcheck_boolean(sysir, sysir->types[instruction.three.dest]);
|
||||
break;
|
||||
case JANET_SYSOP_ADDRESS:
|
||||
rcheck_pointer(sysir, sysir->types[instruction.two.dest]);
|
||||
rcheck_pointer(sysir, instruction.two.dest);
|
||||
break;
|
||||
case JANET_SYSOP_BRANCH:
|
||||
case JANET_SYSOP_BRANCH_NOT:
|
||||
@ -1523,7 +1530,7 @@ void janet_sys_ir_lower_to_c(JanetSysIRLinkage *linkage, JanetBuffer *buffer) {
|
||||
break;
|
||||
}
|
||||
case JANET_SYSOP_ADDRESS:
|
||||
janet_formatb(buffer, " _r%u = (char *) &", instruction.two.dest);
|
||||
janet_formatb(buffer, " _r%u = (void *) &", instruction.two.dest);
|
||||
op_or_const(ir, buffer, instruction.two.src);
|
||||
janet_formatb(buffer, ";\n");
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user