Commit 6956cb3c authored by Kunshan Wang's avatar Kunshan Wang

Hello world example in Python

parent 5ae18741
import sys
import ctypes, ctypes.util
from libmupython2 import *
def slurp(filename):
with open(filename) as t:
return t.read()
prelude_uir = slurp("examples/prelude.uir")
helloworld_uir = slurp("examples/helloworld.uir")
helloworld_hail = slurp("examples/helloworld.hail")
libc = ctypes.CDLL(ctypes.util.find_library("c"))
libc.write.restype = ctypes.c_ssize_t
libc.write.argtypes = [ctypes.c_int, ctypes.c_void_p, ctypes.c_size_t]
dll = MuRefImpl2StartDLL("../cbinding/libmurefimpl2start.so")
mu = dll.mu_refimpl2_new()
with mu.new_context() as ctx:
# frequently used function
id_of = ctx.id_of
# Load bundles and hail scripts.
ctx.load_bundle(prelude_uir)
ctx.load_bundle(helloworld_uir)
ctx.load_hail(helloworld_hail)
# Perpare the C function pointers:
write_addr = ctypes.cast(libc.write, ctypes.c_void_p).value
print("write_addr = ", write_addr, hex(write_addr))
hwrite_addr = ctx.handle_from_fp(id_of("@write.fp"), write_addr)
hwrite_g = ctx.handle_from_global(id_of("@write.g"))
ctx.store(hwrite_g, hwrite_addr)
# Prepare args.
## new string array
nargs = len(sys.argv)
hnargs = ctx.handle_from_int(nargs, 64)
args = ctx.new_hybrid(id_of("@array_ref_string"), hnargs)
## length
args_ir = ctx.get_iref(args)
args0_ir = ctx.get_field_iref(args_ir, 0)
ctx.store(args0_ir, hnargs)
## elements
argsv_ir = ctx.get_var_part_iref(args_ir)
for i, arg in enumerate(sys.argv):
with DelayedDisposer() as x: ### auto dispose
### new string
arglen = len(arg)
harglen = x << ctx.handle_from_int(arglen, 64)
harg = x << ctx.new_hybrid(id_of("@string"), harglen)
harg_ir = x << ctx.get_iref(harg)
### I ignored the hash
### length
harg1_ir = x << ctx.get_field_iref(harg_ir, 1)
ctx.store(harg1_ir, harglen)
### characters
hargv_ir = x << ctx.get_var_part_iref(harg_ir)
for j, ch in enumerate(arg):
with DelayedDisposer() as y: ### auto dispose
hj = y << ctx.handle_from_int(j, 64)
hargvj_ir = y << ctx.shift_iref(hargv_ir, hj)
hch = y << ctx.handle_from_int(ord(ch), 8)
ctx.store(hargvj_ir, hch)
### add to the array
hi = x << ctx.handle_from_int(i, 64)
argsvi_ir = x << ctx.shift_iref(argsv_ir, hi)
ctx.store(argsvi_ir, harg)
# Create a box to receive the return value from @main.
# Mu stacks cannot return values to the client, so only the memory can be
# used to exchange data.
rvbox = ctx.new_fixed(id_of("@i32"))
_start = ctx.handle_from_func(id_of("@_start"))
st = ctx.new_stack(_start)
th = ctx.new_thread(st, PassValues(args, rvbox))
mu.execute()
rvbox_ir = ctx.get_iref(rvbox)
hrv = ctx.load(rvbox_ir).cast(MuIntValue)
rv = ctx.handle_to_sint(hrv)
print("Returned from Mu. Return value = {}".format(rv))
.newhybrid $hw <@string> 12
.init $hw = {
0
12
{ 0x48 0x65 0x6c 0x6c 0x6f 0x20 0x77 0x6f 0x72 0x6c 0x64 0x21 }
}
.newhybrid $nl <@string> 1
.init $nl = { 0 1 { 0x0a } }
.init @hello_world.g = $hw
.init @newline.g = $nl
.typedef @string = hybrid<
@i64 // hash
@i64 // length
@i8 // bytes
>
.typedef @ref_string = ref<@string>
.global @hello_world.g <@ref_string>
.global @newline.g <@ref_string>
.typedef @array_ref_string = hybrid<
@i64 // length
@ref_string // elements
>
.typedef @ref_array_ref_string = ref<@array_ref_string>
.typedef @iref_ref_string = iref<@ref_string>
.funcsig @_start.sig = (@ref_array_ref_string @refi32) -> ()
.funcdef @_start VERSION %v1 <@_start.sig> {
%entry(<@ref_array_ref_string> %args <@refi32> %rvbox):
%rv = CALL <@main.sig> @main (%args)
%rvbox_ir = GETIREF <@i32> %rvbox
STORE <@i32> %rvbox_ir %rv
COMMINST @uvm.thread_exit
}
.funcsig @main.sig = (@ref_array_ref_string) -> (@i32)
.funcdef @main VERSION %v1 <@main.sig> {
%entry(<@ref_array_ref_string> %args):
%hw = LOAD <@ref_string> @hello_world.g
CALL <@puts.sig> @puts (%hw)
%args_ir = GETIREF <@array_ref_string> %args
%argsf0_ir = GETFIELDIREF <@array_ref_string 0> %args_ir
%argsv_ir = GETVARPARTIREF <@array_ref_string> %args_ir
%len = LOAD <@i64> %argsf0_ir
BRANCH %head(%argsv_ir @I64_0 %len)
%head(<@iref_ref_string> %argsv_ir <@i64> %i <@i64> %len):
%lt = SLT <@i64> %i %len
BRANCH2 %lt %body(%argsv_ir %i %len) %exit()
%body(<@iref_ref_string> %argsv_ir <@i64> %i <@i64> %len):
%elem_ir = SHIFTIREF <@iref_ref_string @i64> %argsv_ir %i
%str_r = LOAD <@ref_string> %elem_ir
CALL <@puts.sig> @puts (%str_r)
%i2 = ADD <@i64> %i @I64_1
BRANCH %head(%argsv_ir %i2 %len)
%exit():
RET @I32_0
}
.typedef @size_t = int<64>
.funcsig @write.sig = (@i32 @ptrvoid @size_t) -> (@size_t)
.typedef @write.fp = ufuncptr<@write.sig>
.global @write.g <@write.fp>
.funcsig @puts.sig = (@ref_string) -> ()
.funcdef @puts VERSION %v1 <@puts.sig> {
%entry(<@ref_string> %str_r):
CALL <@puts.sig> @print (%str_r)
%nl = LOAD <@ref_string> @newline.g
CALL <@puts.sig> @print (%nl)
RET ()
}
.funcsig @print.sig = (@ref_string) -> ()
.funcdef @print VERSION %v1 <@print.sig> {
%entry(<@ref_string> %str_r):
%str_ir = GETIREF <@string> %str_r
%len_ir = GETFIELDIREF <@string 1> %str_ir
%len = LOAD <@i64> %len_ir
%content_ir = GETVARPARTIREF <@string> %str_ir
%content_ptr = COMMINST @uvm.native.pin <@irefi8> (%content_ir)
%content_ptr_v = PTRCAST <@ptri8 @ptrvoid> %content_ptr
%write = LOAD <@write.fp> @write.g
%rv = CCALL #DEFAULT <@write.fp @write.sig> %write (@I32_1 %content_ptr_v %len)
COMMINST @uvm.native.unpin <@irefi8> (%content_ir)
RET ()
}
.typedef @i1 = int<1>
.typedef @i6 = int<6>
.typedef @i8 = int<8>
.typedef @i16 = int<16>
.typedef @i32 = int<32>
.typedef @i52 = int<52>
.typedef @i64 = int<64>
.typedef @float = float
.typedef @double = double
.typedef @void = void
.typedef @thread = threadref
.typedef @stack = stackref
.typedef @tagref64 = tagref64
.typedef @4xi32 = vector <@i32 4>
.typedef @4xfloat = vector <@float 4>
.typedef @2xdouble = vector <@double 2>
.typedef @refi8 = ref<@i8>
.typedef @refi16 = ref<@i16>
.typedef @refi32 = ref<@i32>
.typedef @refi64 = ref<@i64>
.typedef @reffloat = ref<@float>
.typedef @refdouble = ref<@double>
.typedef @irefi8 = iref<@i8>
.typedef @irefi16 = iref<@i16>
.typedef @irefi32 = iref<@i32>
.typedef @irefi64 = iref<@i64>
.typedef @ireffloat = iref<@float>
.typedef @irefdouble= iref<@double>
.typedef @ptrvoid = uptr<@void>
.typedef @ptri8 = uptr<@i8>
.typedef @ptri16 = uptr<@i16>
.typedef @ptri32 = uptr<@i32>
.typedef @ptri64 = uptr<@i64>
.typedef @ptrfloat = uptr<@float>
.typedef @ptrdouble = uptr<@double>
.typedef @ptrptrvoid = uptr<@ptrvoid>
.typedef @weakrefi64 = weakref<@i64>
.typedef @refvoid = ref<@void>
.typedef @irefvoid = iref<@void>
.typedef @weakrefvoid = weakref<@void>
.const @I32_0 <@i32> = 0
.const @I32_1 <@i32> = 1
.const @I64_0 <@i64> = 0
.const @I64_1 <@i64> = 1
.funcsig @v_v = () -> ()
.typedef @frv_v = funcref<@v_v>
.const @NULLREF <@refvoid> = NULL
.const @NULLIREF <@irefvoid> = NULL
.const @NULLFUNC <@frv_v> = NULL
.const @NULLSTACK <@stack> = NULL
.const @NULLREF_I64 <@refi64> = NULL
.const @NULLIREF_I64 <@irefi64> = NULL
......@@ -793,20 +793,28 @@ class DelayedDisposer(object):
def __init__(self):
self.garbages = []
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type != None:
return False
self.delete_all()
return False
def add(self, handle):
self.garbages.append(handle)
if isinstance(handle, MuValue):
self.garbages.append(handle)
else:
for h in handle:
self.add(h)
return handle
def __lshift__(self, rhs):
return self.add(rhs)
def delete_all(self):
if exc_type != None:
return False
for h in reversed(self.garbages):
h.delete();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment