Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 0:33feccbba3ff, committed 2017-02-15
- Comitter:
- tk_takateku
- Date:
- Wed Feb 15 01:03:35 2017 +0000
- Commit message:
- Commit before publishing
Changed in this revision
diff -r 000000000000 -r 33feccbba3ff main.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,57 @@
+#include "mbed.h"
+
+#include "mrubyc/hal/hal.h"
+#include "mrubyc/mrubyc.h"
+
+DigitalIn mybutton(USER_BUTTON);
+DigitalOut myled(LED1);
+RawSerial mysci(USBTX, USBRX);
+
+extern const uint8_t sample1[];
+extern const uint8_t sample2[];
+
+int hal_write(int fd, const void *buf, size_t nbytes)
+{
+ return mysci.write((const uint8_t *)buf, (int)nbytes, NULL, SERIAL_EVENT_TX_COMPLETE);
+}
+
+int hal_flush(int fd)
+{
+ char char1 = 0;
+ while (mysci.readable())
+ {
+ char1 = mysci.getc();
+ }
+ return 0;
+}
+
+void hal_delay(mrb_vm *vm, mrb_value *v)
+{
+ wait_ms((int)GET_INT_ARG(0));
+}
+
+void hal_led(mrb_vm *vm, mrb_value *v)
+{
+ myled = (int)GET_INT_ARG(0);
+}
+
+void hal_button(mrb_vm *vm, mrb_value *v)
+{
+ int sw = mybutton;
+ SET_INT_RETURN(sw);
+}
+
+int main() {
+ mysci.baud(115200); // 115Kbps
+ mysci.format(8, Serial::None, 1); // 8bt, none parity, stop bit 1
+ mrbc_init();
+ mrbc_define_method(0, mrbc_class_object, "led1_write", hal_led);
+ mrbc_define_method(0, mrbc_class_object, "delay", hal_delay);
+ mrbc_define_method(0, mrbc_class_object, "sw1_read", hal_button);
+ mrbc_create_task( sample1, 0 );
+ mrbc_create_task( sample2, 0 );
+
+ mrbc_run();
+
+}
+
\ No newline at end of file
diff -r 000000000000 -r 33feccbba3ff mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Wed Feb 15 01:03:35 2017 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/ef9c61f8c49f \ No newline at end of file
diff -r 000000000000 -r 33feccbba3ff mrubyc/alloc.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/alloc.c Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,373 @@
+/*! @file
+ @brief
+ mrubyc memory management.
+
+ <pre>
+ Copyright (C) 2015 Kyushu Institute of Technology.
+ Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+
+ Memory management for objects in mruby/c.
+
+ </pre>
+*/
+
+#include <stddef.h>
+#include <string.h>
+#include "alloc.h"
+#include "console.h"
+
+//
+#define ALLOC_TOTAL_MEMORY_SIZE 0x2800
+
+// address space 16bit, 64KB
+#define ALLOC_MAX_BIT 16
+
+// Layer 1st(f) and 2nd(s) model
+// last 4bit is ignored
+// f : size
+// 0 : 0000-007f
+// 1 : 0080-00ff
+// 2 : 0100-01ff
+// 3 : 0200-03ff
+// 4 : 0400-07ff
+// 5 : 0800-0fff
+// 6 : 1000-1fff
+// 7 : 2000-3fff
+// 8 : 4000-7fff
+// 9 : 8000-ffff
+
+#define ALLOC_1ST_LAYER 8
+#define ALLOC_1ST_LAYER_BIT ALLOC_1ST_LAYER
+#define ALLOC_1ST_LAYER_MASK 0xff80
+
+// 2nd layer size
+#define ALLOC_2ND_LAYER 8
+#define ALLOC_2ND_LAYER_BIT 3
+#define ALLOC_2ND_LAYER_MASK 0x0070
+
+// memory
+static uint8_t memory_pool[ALLOC_TOTAL_MEMORY_SIZE];
+
+// define flags
+#define FLAG_TAIL_BLOCK 1
+#define FLAG_NOT_TAIL_BLOCK 0
+#define FLAG_FREE_BLOCK 1
+#define FLAG_USED_BLOCK 0
+
+// memory block header
+struct USED_BLOCK {
+ unsigned int t: 1; /* FLAG_TAIL_BLOCK or FLAG_NOT_TAIL_BLOCK */
+ unsigned int f: 1; /* FLAG_FREE_BLOCK or BLOCK_IS_NOT_FREE */
+ unsigned int size: 14; /* block size, header included */
+ struct USED_BLOCK *prev; /* link to previous block */
+ uint8_t data[];
+};
+
+struct FREE_BLOCK {
+ unsigned int t: 1; /* 0: not tail, 1: tail */
+ unsigned int f: 1; /* 0: not free, 1: free */
+ unsigned int size: 14; /* block size, header included */
+ struct FREE_BLOCK *prev; /* link to previous block */
+ struct FREE_BLOCK *next_free;
+ struct FREE_BLOCK *prev_free;
+};
+
+// free memory bitmap
+static struct FREE_BLOCK *free_blocks[ALLOC_1ST_LAYER * ALLOC_2ND_LAYER];
+
+
+// calc f and s, and returns index of free_blocks
+static int calc_index(uint32_t alloc_size)
+{
+ if( alloc_size < 16 ) alloc_size = 16;
+
+ // 1st layer
+ int f = 0;
+ uint32_t f_bit = ALLOC_1ST_LAYER_MASK;
+ uint32_t s_bit = ALLOC_2ND_LAYER_MASK;
+ while( (alloc_size & f_bit) != 0 ){
+ f++;
+ f_bit <<= 1;
+ s_bit <<= 1;
+ }
+
+ // 2nd layer
+ int s = (alloc_size & s_bit) >> (f + 4);
+
+ return f * ALLOC_2ND_LAYER + s;
+}
+
+
+//
+static void add_free_block(struct FREE_BLOCK *block)
+{
+ block->f = FLAG_FREE_BLOCK;
+ int index = calc_index(block->size);
+
+ block->prev_free = NULL;
+ block->next_free = free_blocks[index];
+ if( free_blocks[index] != NULL ){
+ free_blocks[index]->prev_free = block;
+ }
+ free_blocks[index] = block;
+}
+
+
+// initialize free block
+void mrbc_init_alloc(void)
+{
+ // clear links to free block
+ int i;
+ for( i=0 ; i<ALLOC_1ST_LAYER*ALLOC_2ND_LAYER ; i++ ){
+ free_blocks[i] = NULL;
+ }
+
+ // memory pool
+ struct FREE_BLOCK *block = (struct FREE_BLOCK *)memory_pool;
+ block->t = FLAG_TAIL_BLOCK;
+ block->size = ALLOC_TOTAL_MEMORY_SIZE;
+ add_free_block(block);
+}
+
+// split block *alloc by size
+static struct FREE_BLOCK *split_block(struct FREE_BLOCK *alloc, int size)
+{
+ if( alloc->size < size + 24 ) return NULL;
+
+ // split block, free
+ uint8_t *p = (uint8_t *)alloc;
+ struct FREE_BLOCK *split = (struct FREE_BLOCK *)(p + size);
+ struct FREE_BLOCK *next = (struct FREE_BLOCK *)(p + alloc->size);
+ split->size = alloc->size - size;
+ split->prev = alloc;
+ split->f = FLAG_FREE_BLOCK;
+ split->t = alloc->t;
+ alloc->size = size;
+ alloc->f = FLAG_USED_BLOCK;
+ alloc->t = FLAG_NOT_TAIL_BLOCK;
+ if( split->t == FLAG_NOT_TAIL_BLOCK ){
+ next->prev = split;
+ }
+
+ return split;
+}
+
+
+// just remove the free_block *remove from index
+static void remove_index(struct FREE_BLOCK *remove)
+{
+ // remove is top of linked list?
+ if( remove->prev_free == NULL ){
+ int index = calc_index(remove->size);
+ free_blocks[index] = remove->next_free;
+ if( free_blocks[index] != NULL ){
+ free_blocks[index]->prev = NULL;
+ }
+ } else {
+ remove->prev_free->next_free = remove->next_free;
+ if( remove->next_free != NULL ){
+ remove->next_free->prev_free = remove->prev_free;
+ }
+ }
+}
+
+// memory allocation
+uint8_t *mrbc_raw_alloc(uint32_t size)
+{
+ uint32_t alloc_size = size + sizeof(struct USED_BLOCK);
+
+ int index = calc_index(alloc_size);
+ while( index < ALLOC_1ST_LAYER*ALLOC_2ND_LAYER && free_blocks[index] == NULL ){
+ index++;
+ }
+ if( index >= ALLOC_1ST_LAYER*ALLOC_2ND_LAYER ){
+ // out of memory
+ console_print("Fatal error: Out of memory.\n");
+ return NULL;
+ }
+
+ // alloc a free block
+ struct FREE_BLOCK *alloc = free_blocks[index];
+ alloc->f = FLAG_USED_BLOCK;
+ remove_index(alloc);
+
+ // split a block
+ struct FREE_BLOCK *release = split_block(alloc, alloc_size);
+ if( release != NULL ){
+ // split alloc -> alloc + release
+ int index = calc_index(release->size);
+ release->next_free = free_blocks[index];
+ release->prev_free = NULL;
+ free_blocks[index] = release;
+ if( release->next_free != NULL ){
+ release->next_free->prev_free = release;
+ }
+ }
+
+ return ((struct USED_BLOCK *)alloc)->data;
+}
+
+
+// merge ptr1 and ptr2
+// ptr2 will disappear
+static void merge(struct FREE_BLOCK *ptr1, struct FREE_BLOCK *ptr2)
+{
+ // merge ptr1 and ptr2
+ ptr1->t = ptr2->t;
+ ptr1->size += ptr2->size;
+
+ // update block info
+ if( ptr1->t == FLAG_NOT_TAIL_BLOCK ){
+ uint8_t *p = (uint8_t *)ptr1;
+ struct FREE_BLOCK *next = (struct FREE_BLOCK *)(p + ptr1->size);
+ next->prev = ptr1;
+ }
+}
+
+// memory release
+void mrbc_raw_free(void *ptr)
+{
+ // get free block
+ uint8_t *p = ptr;
+ struct FREE_BLOCK *free_ptr = (struct FREE_BLOCK *)(p - sizeof(struct USED_BLOCK));
+ free_ptr->f = FLAG_FREE_BLOCK;
+
+ // check next block, merge?
+ p = (uint8_t *)free_ptr;
+ struct FREE_BLOCK *next_ptr = (struct FREE_BLOCK *)(p + free_ptr->size);
+ if( free_ptr->t == FLAG_NOT_TAIL_BLOCK && next_ptr->f == FLAG_FREE_BLOCK ){
+ remove_index(next_ptr);
+ merge(free_ptr, next_ptr);
+ }
+
+ // check prev block, merge?
+ struct FREE_BLOCK *prev_ptr = free_ptr->prev;
+ if( prev_ptr != NULL && prev_ptr->f == FLAG_FREE_BLOCK ){
+ remove_index(prev_ptr);
+ merge(prev_ptr, free_ptr);
+ free_ptr = prev_ptr;
+ }
+
+ // free, add to index
+ add_free_block(free_ptr);
+}
+
+
+// simple realloc
+uint8_t *mrbc_raw_realloc(uint8_t *ptr, uint32_t size)
+{
+ uint8_t *new_ptr = mrbc_raw_alloc(size);
+ if( new_ptr == NULL ) return NULL; // ENOMEM
+
+ // get block info
+ uint8_t *src_ptr = ptr;
+ struct USED_BLOCK *src_block = (struct USED_BLOCK *)(src_ptr - sizeof(struct USED_BLOCK));
+
+ // copy size
+ int copy_size;
+ if( size > src_block->size-sizeof(struct USED_BLOCK) ){
+ copy_size = src_block->size - sizeof(struct USED_BLOCK);
+ } else {
+ copy_size = size;
+ }
+
+ // copy and free
+ memcpy(new_ptr, src_ptr, copy_size);
+ mrbc_raw_free(ptr);
+
+ return new_ptr;
+}
+
+// for debug
+#ifdef MRBC_DEBUG
+#include <stdio.h>
+void mrbc_alloc_debug(void)
+{
+ struct FREE_BLOCK *ptr = (struct FREE_BLOCK *)memory_pool;
+ printf("-----\naddress f size\n");
+ do {
+ uint8_t *p = (uint8_t *)ptr;
+ printf("%p: %d %x\n", p, ptr->f, ptr->size);
+ if( ptr->t == FLAG_TAIL_BLOCK ) break;
+ p += ptr->size;
+ ptr = (struct FREE_BLOCK *)p;
+ } while(1);
+
+ printf("-----\n");
+ int i;
+ for( i=0 ; i<ALLOC_1ST_LAYER * ALLOC_2ND_LAYER ; i++ ){
+ if( free_blocks[i] == NULL ) continue;
+ printf("free[%d]\n", i);
+ struct FREE_BLOCK *ptr = free_blocks[i];
+ while( ptr != NULL ){
+ printf(" %p: size=%d\n", ptr, ptr->size);
+ ptr = ptr->next_free;
+ }
+ }
+}
+#endif
+
+//// for mruby/c
+
+struct MEM_WITH_VM {
+ uint8_t vm_id;
+ uint8_t data[];
+};
+
+uint8_t *mrbc_alloc(mrb_vm *vm, int size)
+{
+ int alloc_size = size + sizeof(struct MEM_WITH_VM);
+ struct MEM_WITH_VM *alloc_block =
+ (struct MEM_WITH_VM *)mrbc_raw_alloc(alloc_size);
+ if( alloc_block == NULL ) return NULL; // ENOMEM
+
+ alloc_block->vm_id = (vm != NULL) ? vm->vm_id : 0;
+ return alloc_block->data;
+}
+
+
+uint8_t *mrbc_realloc(mrb_vm *vm, void *ptr, int size)
+{
+ int alloc_size = size + sizeof(struct MEM_WITH_VM);
+ struct MEM_WITH_VM *alloc_block =
+ (struct MEM_WITH_VM *)mrbc_raw_realloc(ptr, alloc_size);
+ if( alloc_block == NULL ) return NULL; // ENOMEM
+
+ alloc_block->vm_id = (vm != NULL) ? vm->vm_id : 0;
+ return alloc_block->data;
+}
+
+
+void mrbc_free(mrb_vm *vm, void *ptr)
+{
+ if( ptr == NULL ) return;
+
+ uint8_t *p = (uint8_t *)ptr;
+ struct MEM_WITH_VM *free_block = (struct MEM_WITH_VM *)(p - sizeof(struct MEM_WITH_VM));
+ mrbc_raw_free(free_block);
+}
+
+
+void mrbc_free_all(mrb_vm *vm)
+{
+ int vm_id = vm->vm_id;
+
+ struct USED_BLOCK *ptr = (struct USED_BLOCK *)memory_pool;
+ while( ptr->t != FLAG_TAIL_BLOCK ){
+ struct MEM_WITH_VM *vm_ptr = (struct MEM_WITH_VM *)(ptr->data);
+ if( ptr->f == FLAG_FREE_BLOCK || vm_ptr->vm_id != vm_id ){
+ uint8_t *p = (uint8_t *)ptr;
+ ptr = (struct USED_BLOCK *)(p + ptr->size);
+ continue;
+ }
+ if( vm_ptr->vm_id != vm_id ) continue;
+ // free a block
+ struct USED_BLOCK *next_ptr = ptr->prev;
+ if( next_ptr == NULL ) next_ptr = ptr;
+ mrbc_raw_free(ptr->data);
+ ptr = next_ptr;
+ }
+}
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/alloc.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/alloc.h Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,43 @@
+/*! @file
+ @brief
+ mrubyc memory management.
+
+ <pre>
+ Copyright (C) 2015 Kyushu Institute of Technology.
+ Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+
+ Memory management for objects in mruby/c.
+
+ </pre>
+*/
+
+#ifndef MRBC_SRC_ALLOC_H_
+#define MRBC_SRC_ALLOC_H_
+
+#include <stdint.h>
+#include "vm.h" // for mruby/c
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void mrbc_init_alloc(void);
+uint8_t *mrbc_raw_alloc(uint32_t size);
+uint8_t *mrbc_raw_realloc(uint8_t *ptr, uint32_t size);
+void mrbc_raw_free(void *ptr);
+
+void mrbc_alloc_debug(void);
+
+// for mruby/c
+uint8_t *mrbc_alloc(mrb_vm *vm, int size);
+uint8_t *mrbc_realloc(mrb_vm *vm, void *ptr, int size);
+void mrbc_free(mrb_vm *vm, void *ptr);
+void mrbc_free_all(mrb_vm *vm);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/c_array.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/c_array.c Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,175 @@
+#include <stddef.h>
+
+#include "c_array.h"
+
+#include "alloc.h"
+#include "class.h"
+#include "static.h"
+#include "value.h"
+
+// Internal use only
+// get size of array
+static int array_size(mrb_value *v)
+{
+ mrb_value *array = v->value.obj;
+ return array->value.i;
+}
+
+
+// Array#!=
+static void c_array_neq(mrb_vm *vm, mrb_value *v)
+{
+ if( mrbc_eq(v, v+1) ){
+ SET_FALSE_RETURN();
+ } else {
+ SET_TRUE_RETURN();
+ }
+}
+
+// Array = empty?
+static void c_array_empty(mrb_vm *vm, mrb_value *v)
+{
+ if( array_size(v) > 0 ){
+ SET_FALSE_RETURN();
+ } else {
+ SET_TRUE_RETURN();
+ }
+}
+
+// Array = size
+static void c_array_size(mrb_vm *vm, mrb_value *v)
+{
+ int cnt = array_size(v);
+ SET_INT_RETURN( cnt );
+}
+
+// Array = []
+static void c_array_get(mrb_vm *vm, mrb_value *v)
+{
+ int pos = GET_INT_ARG(0);
+ mrb_value *array = v->value.obj;
+
+ if( pos >= 0 && pos < array->value.i ){
+ *v = array[pos+1];
+ } else {
+ SET_NIL_RETURN();
+ }
+}
+
+// Array = []=
+static void c_array_set(mrb_vm *vm, mrb_value *v)
+{
+ int pos = GET_INT_ARG(0);
+ mrb_value *array = v->value.obj;
+
+ if( pos >= 0 && pos < array->value.i ){
+ array[pos+1] = GET_ARG(1);
+ } else {
+ SET_NIL_RETURN();
+ }
+}
+
+// Array = operator +
+static void c_array_plus(mrb_vm *vm, mrb_value *v)
+{
+ // because realloc is not ready in alloc.c,
+ // use free and alloc
+ mrb_value *array1 = v->value.array;
+ mrb_value *array2 = GET_ARY_ARG(0).value.array;
+ int len1 = array1->value.i;
+ int len2 = array2->value.i;
+ mrb_value *new_array = (mrb_value *)mrbc_alloc(vm, sizeof(mrb_value)*(len1+len2+1));
+
+ if( new_array == NULL ) return; // ENOMEM
+
+ new_array->tt = MRB_TT_FIXNUM;
+ new_array->value.i = len1+len2;
+ mrb_value *p = new_array + 1;
+ int i;
+ for( i=0 ; i<len1 ; i++ ){
+ *p++ = array1[i+1];
+ }
+ for( i=0 ; i<len2 ; i++ ){
+ *p++ = array2[i+1];
+ }
+ mrbc_free(vm, array1);
+ mrbc_free(vm, array2);
+ // return
+ v->value.array = new_array;
+}
+
+
+static void c_array_index(mrb_vm *vm, mrb_value *v)
+{
+ int len = v->value.array->value.i;
+ mrb_value *array = v->value.array + 1;
+ mrb_value value = GET_ARG(0);
+
+ int i;
+ for( i=0 ; i<len ; i++ ){
+ // check EQ
+ if( mrbc_eq(array+i, &value) ) break;
+ }
+ if( i<len ){
+ SET_INT_RETURN(i);
+ } else {
+ SET_NIL_RETURN();
+ }
+}
+
+static void c_array_first(mrb_vm *vm, mrb_value *v)
+{
+ if( GET_TT_ARG(0) == MRB_TT_FIXNUM ){
+ mrb_value *array = v->value.array + 1;
+ SET_RETURN( array[0] );
+ } else {
+ SET_NIL_RETURN();
+ }
+}
+
+static void c_array_last(mrb_vm *vm, mrb_value *v)
+{
+ if( GET_TT_ARG(0) == MRB_TT_FIXNUM ){
+ int len = v->value.array->value.i;
+ mrb_value *array = v->value.array + 1;
+ SET_RETURN( array[len-1] );
+ } else {
+ SET_NIL_RETURN();
+ }
+}
+
+static void c_array_pop(mrb_vm *vm, mrb_value *v)
+{
+ mrb_object *obj = v->value.obj;
+ mrb_object *tmp = obj->next;
+ while( tmp->next ){
+ obj = obj->next;
+ tmp = obj->next;
+ }
+ obj->next = tmp->next;
+ SET_INT_RETURN(tmp->value.i);
+}
+
+
+void mrbc_init_class_array(mrb_vm *vm)
+{
+ // Array
+ mrbc_class_array = mrbc_class_alloc(vm, "Array", mrbc_class_object);
+
+ mrbc_define_method(vm, mrbc_class_array, "!=", c_array_neq);
+ mrbc_define_method(vm, mrbc_class_array, "count", c_array_size);
+ mrbc_define_method(vm, mrbc_class_array, "length", c_array_size);
+ mrbc_define_method(vm, mrbc_class_array, "size", c_array_size);
+ mrbc_define_method(vm, mrbc_class_array, "+", c_array_plus);
+ mrbc_define_method(vm, mrbc_class_array, "empty?", c_array_empty);
+ mrbc_define_method(vm, mrbc_class_array, "[]", c_array_get);
+ mrbc_define_method(vm, mrbc_class_array, "at", c_array_get);
+ mrbc_define_method(vm, mrbc_class_array, "[]=", c_array_set);
+ mrbc_define_method(vm, mrbc_class_array, "index", c_array_index);
+
+
+ mrbc_define_method(vm, mrbc_class_array, "first", c_array_first);
+ mrbc_define_method(vm, mrbc_class_array, "last", c_array_last);
+ mrbc_define_method(vm, mrbc_class_array, "pop", c_array_pop);
+}
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/c_array.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/c_array.h Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,32 @@
+/*! @file
+ @brief
+
+
+ <pre>
+ Copyright (C) 2015 Kyushu Institute of Technology.
+ Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+
+
+ </pre>
+*/
+
+#ifndef MRBC_SRC_C_ARRAY_H_
+#define MRBC_SRC_C_ARRAY_H_
+
+#include "vm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+void mrbc_init_class_array(mrb_vm *vm);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/c_hash.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/c_hash.c Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,90 @@
+#include <stddef.h>
+
+#include "c_hash.h"
+
+#include "alloc.h"
+#include "class.h"
+#include "static.h"
+#include "value.h"
+
+static void c_hash_size(mrb_vm *vm, mrb_value *v)
+{
+ mrb_value *hash = v->value.obj;
+
+ SET_INT_RETURN(hash->value.obj->value.i);
+}
+
+
+// Hash = []
+static void c_hash_get(mrb_vm *vm, mrb_value *v)
+{
+ mrb_value *hash = v->value.obj->value.obj;
+ int i;
+ int n = hash->value.i; // hash size
+ mrb_value key = GET_ARG(0); // search key
+
+ // ptr: 1st entry(key) of hash
+ mrb_value *ptr = &hash[1];
+
+ for( i=0 ; i<n ; i++ ){
+ if( mrbc_eq(ptr, &key) ){
+ SET_RETURN( *(ptr+1) );
+ return;
+ }
+ ptr += 2;
+ }
+
+ SET_NIL_RETURN();
+}
+
+// Hash = []=
+static void c_hash_set(mrb_vm *vm, mrb_value *v)
+{
+ mrb_value *hash = v->value.obj->value.obj;
+ int i;
+ int n = hash[0].value.i; // hash size
+ mrb_value key = GET_ARG(0); // search key
+ mrb_value val = GET_ARG(1); // new value
+
+ mrb_value *ptr = &hash[1];
+ for( i=0 ; i<n ; i++ ){
+ if( mrbc_eq(ptr, &key) ){
+ *(ptr+1) = val; // Change value
+ return;
+ }
+ }
+
+ // key was not found
+ // add hash entry (key and val)
+ int new_size = (n+1)*2 + 1;
+
+ // use alloc instead of realloc, realloc has some bugs?
+ mrb_value *new_hash = (mrb_value *)mrbc_alloc(vm, sizeof(mrb_value)*new_size);
+ if( new_hash == NULL ) return; // ENOMEM
+
+ mrb_value *src = &hash[1];
+ mrb_value *dst = &new_hash[1];
+ for( i=0 ; i<n ; i++ ){
+ *dst++ = *src++; // copy key
+ *dst++ = *src++; // copy value
+ }
+ new_hash[0].tt = MRB_TT_FIXNUM;
+ new_hash[0].value.i = n+1;
+ *dst++ = key;
+ *dst = val;
+ mrbc_free(vm, v->value.obj->value.obj);
+ v->value.obj->value.obj = new_hash;
+}
+
+
+void mrbc_init_class_hash(mrb_vm *vm)
+{
+ // Hash
+ mrbc_class_hash = mrbc_class_alloc(vm, "Hash", mrbc_class_object);
+
+ mrbc_define_method(vm, mrbc_class_hash, "size", c_hash_size);
+ mrbc_define_method(vm, mrbc_class_hash, "[]", c_hash_get);
+ mrbc_define_method(vm, mrbc_class_hash, "[]=", c_hash_set);
+
+}
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/c_hash.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/c_hash.h Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,32 @@
+/*! @file
+ @brief
+
+
+ <pre>
+ Copyright (C) 2015 Kyushu Institute of Technology.
+ Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+
+
+ </pre>
+*/
+
+#ifndef MRBC_SRC_C_HASH_H_
+#define MRBC_SRC_C_HASH_H_
+
+#include "vm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+void mrbc_init_class_hash(mrb_vm *vm);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/c_numeric.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/c_numeric.c Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,141 @@
+#include <stdio.h>
+
+#include "vm_config.h"
+#include "c_numeric.h"
+#include "alloc.h"
+#include "class.h"
+#include "static.h"
+#include "value.h"
+#include "console.h"
+
+static void c_fixnum_eq(mrb_vm *vm, mrb_value *v)
+{
+ console_printf("ERROR ==\n");
+}
+
+// Operator %
+static void c_fixnum_mod(mrb_vm *vm, mrb_value *v)
+{
+ int num = GET_INT_ARG(0);
+ SET_INT_RETURN( v->value.i % num );
+}
+
+// Operator <=>
+static void c_fixnum_comp(mrb_vm *vm, mrb_value *v)
+{
+ int num = GET_INT_ARG(0);
+ if(v->value.i > num){
+ SET_INT_RETURN(1);
+ }else if(v->value.i == num){
+ SET_INT_RETURN(0);
+ }else{
+ SET_INT_RETURN(-1);
+ }
+}
+
+// Unary Operator ~; bit operation NOT
+static void c_fixnum_deny(mrb_vm *vm, mrb_value *v)
+{
+ SET_INT_RETURN( (v->value.i + 1) * (-1) );
+}
+
+
+// Operator &; bit operation AND
+static void c_fixnum_and(mrb_vm *vm, mrb_value *v)
+{
+ int num = GET_INT_ARG(0);
+ SET_INT_RETURN(v->value.i & num);
+}
+
+// x-bit left shift for x
+static int32_t shift(int32_t x, int32_t y)
+{
+ if( y >= 33 ){
+ x = 0;
+ } else if( y >= 0 ){
+ x <<= y;
+ } else if( y > -33 ){
+ x = x >> -y;
+ } else {
+ x = 0;
+ }
+ return x;
+}
+
+// Operator <<; bit operation LEFT_SHIFT
+static void c_fixnum_lshift(mrb_vm *vm, mrb_value *v)
+{
+ int num = GET_INT_ARG(0);
+ SET_INT_RETURN( shift(v->value.i, num) );
+}
+
+// Operator >>; bit operation RIGHT_SHIFT
+static void c_fixnum_rshift(mrb_vm *vm, mrb_value *v)
+{
+ int num = GET_INT_ARG(0);
+ SET_INT_RETURN( shift(v->value.i, -num) );
+}
+
+#if MRBC_USE_STRING
+static void c_fixnum_to_s(mrb_vm *vm, mrb_value *v)
+{
+ int num = v->value.i;
+ int i = 0, j = 0;
+ char buf[10];
+ int sign = 0;
+
+ if( num < 0 ){
+ sign = 1;
+ num = -num;
+ }
+ do {
+ buf[i++] = (num % 10) + '0';
+ num = num / 10;
+ } while( num > 0 );
+ if( sign ){
+ buf[i] = '-';
+ } else {
+ i--;
+ }
+ char *str = (char *)mrbc_alloc(vm, i+2);
+ if( str == NULL ) return; // ENOMEM
+ while( i>=0 ){
+ str[j++] = buf[i--];
+ }
+ str[j] = 0;
+ v->tt = MRB_TT_STRING;
+ v->value.str = str;
+}
+#endif
+
+
+
+void mrbc_init_class_fixnum(mrb_vm *vm)
+{
+ // Fixnum
+ mrbc_class_fixnum = mrbc_class_alloc(vm, "Fixnum", mrbc_class_object);
+ mrbc_define_method(vm, mrbc_class_fixnum, "==", c_fixnum_eq);
+ mrbc_define_method(vm, mrbc_class_fixnum, "%", c_fixnum_mod);
+ mrbc_define_method(vm, mrbc_class_fixnum, "<=>", c_fixnum_comp);
+ mrbc_define_method(vm, mrbc_class_fixnum, "~", c_fixnum_deny);
+ mrbc_define_method(vm, mrbc_class_fixnum, "&", c_fixnum_and);
+ mrbc_define_method(vm, mrbc_class_fixnum, "<<", c_fixnum_lshift);
+ mrbc_define_method(vm, mrbc_class_fixnum, ">>", c_fixnum_rshift);
+#if MRBC_USE_STRING
+ mrbc_define_method(vm, mrbc_class_fixnum, "to_s", c_fixnum_to_s);
+#endif
+}
+
+
+// Float
+#if MRBC_USE_FLOAT
+
+void mrbc_init_class_float(mrb_vm *vm)
+{
+ // Float
+ mrbc_class_float = mrbc_class_alloc(vm, "Float", mrbc_class_object);
+
+}
+
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/c_numeric.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/c_numeric.h Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,32 @@
+/*! @file
+ @brief
+
+
+ <pre>
+ Copyright (C) 2015 Kyushu Institute of Technology.
+ Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+
+
+ </pre>
+*/
+
+#ifndef MRBC_SRC_C_NUMERIC_H_
+#define MRBC_SRC_C_NUMERIC_H_
+
+#include "vm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+void mrbc_init_class_fixnum(mrb_vm *vm);
+void mrbc_init_class_float(mrb_vm *vm);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/c_range.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/c_range.c Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,42 @@
+#include <stddef.h>
+
+#include "c_range.h"
+
+#include "alloc.h"
+#include "class.h"
+#include "static.h"
+#include "value.h"
+#include "vm.h"
+
+
+mrb_value mrbc_range_new(mrb_vm *vm, mrb_value *v_st, mrb_value *v_ed, int exclude)
+{
+ mrb_value value;
+ value.tt = MRB_TT_RANGE;
+
+ mrb_value *ptr = (mrb_value*)mrbc_alloc(vm, sizeof(mrb_value)*3);
+ if( ptr == NULL ) return value; // ENOMEM
+
+ if( exclude ){
+ ptr[0].tt = MRB_TT_TRUE;
+ } else {
+ ptr[0].tt = MRB_TT_FALSE;
+ }
+ ptr[1] = *v_st;
+ ptr[2] = *v_ed;
+ value.value.range = ptr;
+
+ return value;
+}
+
+
+
+
+// init class
+void mrbc_init_class_range(mrb_vm *vm)
+{
+ mrbc_class_range = mrbc_class_alloc(vm, "Range", mrbc_class_object);
+
+
+}
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/c_range.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/c_range.h Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,34 @@
+/*! @file
+ @brief
+
+
+ <pre>
+ Copyright (C) 2015 Kyushu Institute of Technology.
+ Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+
+
+ </pre>
+*/
+
+#ifndef MRBC_SRC_C_RANGE_H_
+#define MRBC_SRC_C_RANGE_H_
+
+#include <stdint.h>
+#include "vm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+mrb_value mrbc_range_new(mrb_vm *vm, mrb_value *v_st, mrb_value *v_ed, int exclude);
+
+void mrbc_init_class_range(mrb_vm *vm);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/c_string.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/c_string.c Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,109 @@
+#include <string.h>
+#include "c_string.h"
+
+#include "alloc.h"
+#include "class.h"
+#include "static.h"
+#include "value.h"
+#include "vm.h"
+
+// dupulicate string (clone)
+// returns duplicated string pointer
+char* mrbc_string_dup(mrb_vm *vm, const char *str)
+{
+ int len = strlen((char *)str);
+ char *ptr = (char *)mrbc_alloc(vm, len+1);
+ if( ptr == NULL ) return NULL; // ENOMEM
+
+ strcpy(ptr, str);
+ return ptr;
+}
+
+// catination string
+// returns new string
+char *mrbc_string_cat(mrb_vm *vm, char *s1, const char *s2)
+{
+ int len1 = strlen(s1);
+ int len2 = strlen(s2);
+ char *ptr = (char *)mrbc_alloc(vm, len1+len2+1);
+ if( ptr == NULL ) return NULL; // ENOMEM
+
+ strcpy(ptr, s1);
+ strcpy(ptr+len1, s2);
+ return ptr;
+}
+
+// substr
+// returns new string
+static char *mrbc_string_substr(mrb_vm *vm, char *s, int start, int len)
+{
+ char *ptr = (char *)mrbc_alloc(vm, len+1);
+ if( ptr == NULL ) return NULL; // ENOMEM
+
+ int i;
+ for( i=0 ; i<len ; i++ ){
+ ptr[i] = s[start+i];
+ }
+ ptr[len] = 0;
+ return ptr;
+}
+
+
+// method
+// string size
+static void c_string_size(mrb_vm *vm, mrb_value *v)
+{
+ int cnt = strlen(v->value.str);
+ SET_INT_RETURN( cnt );
+}
+
+
+// method
+// string !=
+static void c_string_neq(mrb_vm *vm, mrb_value *v)
+{
+ if( mrbc_eq(v, v+1) ){
+ SET_FALSE_RETURN();
+ } else {
+ SET_TRUE_RETURN();
+ }
+}
+
+// method
+// string []
+// string[Fixnum]
+static void c_string_idx_get(mrb_vm *vm, mrb_value *v)
+{
+ int index = GET_INT_ARG(0);
+ char *str = mrbc_string_substr(vm, v->value.str, index, 1);
+ v->value.str = str;
+}
+
+
+// method
+// string to_i
+static void c_string_to_fixnum(mrb_vm *vm, mrb_value *v)
+{
+ char *str = v->value.str;
+ int value = 0;
+ while( *str && *str >= '0' && *str <= '9' ){
+ value *= 10;
+ value += *str - '0';
+ str++;
+ }
+ SET_INT_RETURN(value);
+}
+
+
+
+// init class
+void mrbc_init_class_string(mrb_vm *vm)
+{
+ mrbc_class_string = mrbc_class_alloc(vm, "String", mrbc_class_object);
+
+ mrbc_define_method(vm, mrbc_class_string, "size", c_string_size);
+ mrbc_define_method(vm, mrbc_class_string, "length", c_string_size);
+ mrbc_define_method(vm, mrbc_class_string, "!=", c_string_neq);
+ mrbc_define_method(vm, mrbc_class_string, "to_i", c_string_to_fixnum);
+}
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/c_string.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/c_string.h Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,35 @@
+/*! @file
+ @brief
+
+
+ <pre>
+ Copyright (C) 2015 Kyushu Institute of Technology.
+ Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+
+
+ </pre>
+*/
+
+#ifndef MRBC_SRC_C_STRING_H_
+#define MRBC_SRC_C_STRING_H_
+
+#include <stdint.h>
+#include "vm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+void mrbc_init_class_string(mrb_vm *vm);
+
+char *mrbc_string_dup(mrb_vm *vm, const char *str);
+char *mrbc_string_cat(mrb_vm *vm, char *s1, const char *s2);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/c_symbol.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/c_symbol.c Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,42 @@
+#include "c_symbol.h"
+
+#include "class.h"
+#include "static.h"
+#include "value.h"
+#include "symbol.h"
+
+static void c_symbol_to_s(mrb_vm *vm, mrb_value *v)
+{
+ v->tt = MRB_TT_STRING;
+
+ const char *sym = symid_to_str(v->value.i);
+ v->value.str = mrbc_string_dup(vm, sym);
+}
+
+static void c_symbol_to_sym(mrb_vm *vm, mrb_value *v)
+{
+ // nothing
+}
+
+static void c_symbol_equal(mrb_vm *vm, mrb_value *v)
+{
+ if( mrbc_eq(v, &GET_ARG(0)) ){
+ SET_TRUE_RETURN();
+ } else {
+ SET_FALSE_RETURN();
+ }
+}
+
+
+void mrbc_init_class_symbol(mrb_vm *vm)
+{
+ // Symbol
+ mrbc_class_symbol = mrbc_class_alloc(vm, "Symbol", mrbc_class_object);
+
+ mrbc_define_method(vm, mrbc_class_symbol, "to_s", c_symbol_to_s);
+ mrbc_define_method(vm, mrbc_class_symbol, "id2name", c_symbol_to_s);
+ mrbc_define_method(vm, mrbc_class_symbol, "to_sym", c_symbol_to_sym);
+ mrbc_define_method(vm, mrbc_class_symbol, "===", c_symbol_equal);
+}
+
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/c_symbol.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/c_symbol.h Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,32 @@
+/*! @file
+ @brief
+
+
+ <pre>
+ Copyright (C) 2015 Kyushu Institute of Technology.
+ Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+
+
+ </pre>
+*/
+
+#ifndef MRBC_SRC_C_SYMBOL_H_
+#define MRBC_SRC_C_SYMBOL_H_
+
+#include "vm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+void mrbc_init_class_symbol(mrb_vm *vm);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/class.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/class.c Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,263 @@
+/*! @file
+ @brief
+
+ <pre>
+ Copyright (C) 2015-2016 Kyushu Institute of Technology.
+ Copyright (C) 2015-2016 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+
+
+ </pre>
+*/
+
+#include "value.h"
+#include "class.h"
+#include "static.h"
+#include "console.h"
+
+#include "c_array.h"
+#include "c_hash.h"
+#include "c_numeric.h"
+#include "c_string.h"
+#include "c_symbol.h"
+#include "c_range.h"
+
+
+
+//================================================================
+/*!@brief
+ find class from a object
+
+ @param vm
+ @param obj
+ @return pointer to mrb_class
+*/
+mrb_class *find_class_by_object(mrb_vm *vm, mrb_object *obj)
+{
+ mrb_class *cls = mrbc_class_object;
+ switch( obj->tt ){
+ case MRB_TT_ARRAY:
+ cls = mrbc_class_array;
+ break;
+ case MRB_TT_HASH:
+ cls = mrbc_class_hash;
+ break;
+ case MRB_TT_FIXNUM:
+ cls = mrbc_class_fixnum;
+ break;
+ case MRB_TT_SYMBOL:
+ cls = mrbc_class_symbol;
+ break;
+ case MRB_TT_FALSE:
+ cls = mrbc_class_false;
+ break;
+ case MRB_TT_TRUE:
+ cls = mrbc_class_true;
+ break;
+#if MRBC_USE_FLOAT
+ case MRB_TT_FLOAT:
+ cls = mrbc_class_float;
+ break;
+#endif
+#if MRBC_USE_STRING
+ case MRB_TT_STRING:
+ cls = mrbc_class_string;
+ break;
+#endif
+ default:
+ break;
+ }
+ return cls;
+}
+
+
+
+//================================================================
+/*!@brief
+ find method from
+
+ @param vm
+ @param recv
+ @param sym_id
+ @return
+*/
+mrb_proc *find_method(mrb_vm *vm, mrb_value recv, mrb_sym sym_id)
+{
+ mrb_class *cls = find_class_by_object(vm, &recv);
+
+ while( cls != 0 ) {
+ mrb_proc *proc = cls->procs;
+ while( proc != 0 ) {
+ if( proc->sym_id == sym_id ) {
+ return proc;
+ }
+ proc = proc->next;
+ }
+ cls = cls->super;
+ }
+ return 0;
+}
+
+
+
+void mrbc_define_method(mrb_vm *vm, mrb_class *cls, const char *name, mrb_func_t cfunc)
+{
+ mrb_proc *rproc = mrbc_rproc_alloc(vm, name);
+ rproc->c_func = 1; // c-func
+ rproc->next = cls->procs;
+ cls->procs = rproc;
+ rproc->func.func = cfunc;
+}
+
+
+
+
+void mrbc_define_method_proc(mrb_vm *vm, mrb_class *cls, mrb_sym sym_id, mrb_proc *rproc)
+{
+ rproc->c_func = 0;
+ rproc->sym_id = sym_id;
+ rproc->next = cls->procs;
+ cls->procs = rproc;
+}
+
+
+
+// Object - puts
+void c_puts(mrb_vm *vm, mrb_value *v)
+{
+ mrb_value *arg0 = v+1;
+ switch( arg0->tt ){
+ case MRB_TT_FIXNUM:
+ console_printf("%d", arg0->value.i);
+ break;
+ case MRB_TT_NIL:
+ console_printf("");
+ break;
+ case MRB_TT_TRUE:
+ console_printf("true");
+ break;
+ case MRB_TT_FALSE:
+ console_printf("false");
+ break;
+#if MRBC_USE_FLOAT
+ case MRB_TT_FLOAT:
+ console_printf("%f", arg0->value.d);
+ break;
+#endif
+#if MRBC_USE_STRING
+ case MRB_TT_STRING:
+ console_printf("%s", arg0->value.str);
+ break;
+#endif
+ case MRB_TT_RANGE:{
+ mrb_value *ptr = arg0->value.range;
+ if( ptr[0].tt == MRB_TT_TRUE ){
+ console_printf("%d...%d", ptr[1].value.i, ptr[2].value.i);
+ } else {
+ console_printf("%d..%d", ptr[1].value.i, ptr[2].value.i);
+ }
+ } break;
+ default:
+ console_printf("Not supported: MRB_TT_XX(%d)", arg0->tt);
+ break;
+ }
+ console_printf("\n");
+}
+
+// Object !=
+void c_object_neq(mrb_vm *vm, mrb_value *v)
+{
+ if( mrbc_eq(v, &GET_ARG(0)) ){
+ SET_FALSE_RETURN();
+ } else {
+ SET_TRUE_RETURN();
+ }
+}
+
+static void mrbc_init_class_object(mrb_vm *vm)
+{
+ // Class
+ mrbc_class_object = mrbc_class_alloc(vm, "Object", 0);
+ // Methods
+ mrbc_define_method(vm, mrbc_class_object, "puts", c_puts);
+ mrbc_define_method(vm, mrbc_class_object, "!=", c_object_neq);
+}
+
+
+// =============== FalseClass
+
+void c_false_ne(mrb_vm *vm, mrb_value *v)
+{
+ mrb_object *arg0 = v+1;
+ if( arg0->tt == MRB_TT_FALSE ){
+ SET_FALSE_RETURN();
+ } else {
+ SET_TRUE_RETURN();
+ }
+}
+
+void c_false_not(mrb_vm *vm, mrb_value *v)
+{
+ SET_TRUE_RETURN();
+}
+
+static void mrbc_init_class_false(mrb_vm *vm)
+{
+ // Class
+ mrbc_class_false = mrbc_class_alloc(vm, "FalseClass", mrbc_class_object);
+ // Methods
+ mrbc_define_method(vm, mrbc_class_false, "!=", c_false_ne);
+ mrbc_define_method(vm, mrbc_class_false, "!", c_false_not);
+}
+
+
+// =============== TrueClass
+
+void c_true_ne(mrb_vm *vm, mrb_value *v)
+{
+ mrb_object *arg0 = v+1;
+ if( arg0->tt == MRB_TT_TRUE ){
+ SET_FALSE_RETURN();
+ } else {
+ SET_TRUE_RETURN();
+ }
+}
+
+void c_true_not(mrb_vm *vm, mrb_value *v)
+{
+ SET_FALSE_RETURN();
+}
+
+
+
+static void mrbc_init_class_true(mrb_vm *vm)
+{
+ // Class
+ mrbc_class_true = mrbc_class_alloc(vm, "TrueClass", mrbc_class_object);
+ // Methods
+ mrbc_define_method(vm, mrbc_class_true, "!=", c_true_ne);
+ mrbc_define_method(vm, mrbc_class_true, "!", c_true_not);
+
+}
+
+
+void mrbc_init_class(void)
+{
+ mrbc_init_class_object(0);
+ mrbc_init_class_false(0);
+ mrbc_init_class_true(0);
+
+ mrbc_init_class_fixnum(0);
+ mrbc_init_class_symbol(0);
+#if MRBC_USE_FLOAT
+ mrbc_init_class_float(0);
+#endif
+#if MRBC_USE_STRING
+ mrbc_init_class_string(0);
+#endif
+ mrbc_init_class_array(0);
+ mrbc_init_class_range(0);
+ mrbc_init_class_hash(0);
+}
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/class.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/class.h Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,35 @@
+/*! @file
+ @brief
+
+ <pre>
+ Copyright (C) 2015-2016 Kyushu Institute of Technology.
+ Copyright (C) 2015-2016 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+
+
+ </pre>
+*/
+
+#ifndef MRBC_SRC_CLASS_H_
+#define MRBC_SRC_CLASS_H_
+
+#include <stdint.h>
+#include "vm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+mrb_class *find_class_by_object(struct VM *vm, mrb_object *obj);
+mrb_proc *find_method(struct VM *vm, mrb_value recv, mrb_sym sym_id);
+
+void mrbc_init_class(void);
+void mrbc_define_method(struct VM *vm, mrb_class *cls, const char *name, mrb_func_t func);
+void mrbc_define_method_proc(struct VM *vm, mrb_class *cls, mrb_sym sym_id, mrb_proc *rproc);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/console.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/console.c Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,211 @@
+/*! @file
+ @brief
+ console I/O module.
+
+ <pre>
+ Copyright (C) 2015 Kyushu Institute of Technology.
+ Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+
+ </pre>
+*/
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdint.h>
+#include "hal/hal.h"
+#include "console.h"
+
+
+//================================================================
+/*! output string with format
+
+ @param value output value
+ @param align left(-1) or right(1)
+ @param w width
+ @param base n base
+ @param pad padding character
+*/
+static void format_output_str(const char *value, int align, int w, char pad)
+{
+ if( !value ) return;
+
+ int len = strlen(value);
+ int n_pad = w - len;
+
+ if( align == 1 ) {
+ while( n_pad-- > 0 ) {
+ console_putchar(pad);
+ }
+ }
+ hal_write(1, value, len);
+ while( n_pad-- > 0 ) {
+ console_putchar(pad);
+ }
+}
+
+
+//================================================================
+/*! output int value with format
+
+ @param value output value
+ @param align left(-1) or right(1)
+ @param w width
+ @param base n base
+ @param pad padding character
+*/
+static void format_output_int(int32_t value, int align, int w, int base, char pad)
+{
+ char buf[21];
+ int sign = 0;
+ int idx = sizeof(buf);
+ buf[--idx] = 0;
+
+ if( value < 0 ) {
+ sign = -1;
+ value = -value;
+ }
+
+ do {
+ buf[--idx] = "0123456789ABCDEF"[value % base];
+ value /= base;
+ } while( value != 0 && idx != 0 );
+
+ if( sign < 0 && align > 0 && pad == '0' ) {
+ console_putchar('-'); // when "%08d",-12345 then "-0012345"
+ w--;
+ } else if( sign < 0 && idx != 0 ) {
+ buf[--idx] = '-';
+ }
+
+ format_output_str(buf + idx, align, w, pad);
+}
+
+
+//================================================================
+/*! output unsigned int value with format
+
+ @param value output value
+ @param align left(-1) or right(1)
+ @param w width
+ @param base n base
+ @param pad padding character
+*/
+static void format_output_uint(uint32_t value, int align, int w, int base, char pad)
+{
+ char buf[21];
+ int idx = sizeof(buf);
+ buf[--idx] = 0;
+
+ do {
+ buf[--idx] = "0123456789ABCDEF"[value % base];
+ value /= base;
+ } while( value != 0 && idx != 0 );
+
+ format_output_str(buf + idx, align, w, pad);
+}
+
+
+//================================================================
+/*! output a character
+
+ @param c character
+*/
+void console_putchar(char c)
+{
+ hal_write(1, &c, 1);
+}
+
+
+//================================================================
+/*! output string
+
+ @param str str
+*/
+void console_print(const char *str)
+{
+ hal_write(1, str, strlen(str));
+}
+
+
+//================================================================
+/*! output formatted string
+
+ @param fmt format string.
+ @note
+*/
+void console_printf(const char *fmt, ...)
+{
+ va_list params;
+ va_start(params, fmt);
+
+ int c;
+ while((c = *fmt++)) {
+ if( c != '%' ) {
+ console_putchar(c);
+ continue;
+ }
+
+ int align = 1; // left(-1) or right(1)
+ char pad = ' '; // padding
+ int w = 0; // width
+ while( 1 ) {
+ switch( (c = *fmt++) ) {
+ case '-':
+ align = -1;
+ break;
+
+ case '0':
+ if( pad == ' ' ) {
+ pad = '0';
+ break;
+ }
+ // fall through.
+
+ case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9':
+ w = w * 10 + (c - '0');
+ break;
+
+ case '\0':
+ goto L_return;
+
+ default:
+ goto L_exit;
+ }
+ }
+
+L_exit:
+ switch(c) {
+ case 's':
+ format_output_str(va_arg(params, char *), align, w, pad);
+ break;
+
+ case 'd':
+ case 'i':
+ format_output_int(va_arg(params, int), align, w, 10, pad);
+ break;
+
+ case 'u':
+ format_output_uint(va_arg(params, unsigned int), align, w, 10, pad);
+ break;
+
+ case 'X':
+ case 'x':
+ format_output_uint(va_arg(params, unsigned int), align, w, 16, pad);
+ break;
+
+ case 'c':
+ console_putchar(va_arg(params, int)); // ignore "%03c" and others.
+ break;
+
+ default:
+ console_putchar(c);
+ }
+ }
+
+L_return:
+ va_end(params);
+}
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/console.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/console.h Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,30 @@
+/*! @file
+ @brief
+
+
+ <pre>
+ Copyright (C) 2015 Kyushu Institute of Technology.
+ Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+
+
+ </pre>
+*/
+
+#ifndef MRBC_SRC_CONSOLE_H_
+#define MRBC_SRC_CONSOLE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void console_putchar(const char c);
+void console_print(const char *str);
+void console_printf(const char *fmt, ...);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/errorcode.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/errorcode.h Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,56 @@
+/*! @file
+ @brief
+
+
+ <pre>
+ Copyright (C) 2015 Kyushu Institute of Technology.
+ Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+
+
+ </pre>
+*/
+
+#ifndef MRBC_SRC_ERRORCODE_H_
+#define MRBC_SRC_ERRORCODE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* no error */
+#define NO_ERROR 0
+
+/* unknown */
+#define UNKNOWN_ERROR 0x0000ffff
+
+/* load_file */
+#define LOAD_FILE_ERROR (0x0100 << 16)
+#define LOAD_FILE_ERROR_MALLOC (LOAD_FILE_ERROR | 0x0001)
+#define LOAD_FILE_ERROR_NOFILE (LOAD_FILE_ERROR | 0x0002)
+
+#define LOAD_FILE_HEADER_ERROR (0x0101 << 16)
+#define LOAD_FILE_HEADER_ERROR_RITE (LOAD_FILE_HEADER_ERROR) | 0x0001)
+#define LOAD_FILE_HEADER_ERROR_VERSION (LOAD_FILE_HEADER_ERROR | 0x0002)
+#define LOAD_FILE_HEADER_ERROR_CRC (LOAD_FILE_HEADER_ERROR | 0x0003)
+#define LOAD_FILE_HEADER_ERROR_MATZ (LOAD_FILE_HEADER_ERROR | 0x0004)
+
+#define LOAD_FILE_IREP_ERROR (0x0102 << 16)
+#define LOAD_FILE_IREP_ERROR_IREP (LOAD_FILE_IREP_ERROR | 0x0001)
+#define LOAD_FILE_IREP_ERROR_VERSION (LOAD_FILE_IREP_ERROR | 0x0002)
+#define LOAD_FILE_IREP_ERROR_ALLOCATION (LOAD_FILE_IREP_ERROR | 0x0003)
+
+/* VM execution */
+#define VM_EXEC_ERROR (0x1000 << 16)
+#define VM_EXEC_STATIC_OVWEFLOW_VM (VM_EXEC_ERROR | 0x0001)
+#define VM_EXEC_STATIC_OVWEFLOW_IREP (VM_EXEC_ERROR | 0x0002)
+#define VM_EXEC_STATIC_OVWEFLOW_CALLINFO (VM_EXEC_ERROR | 0x0003)
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/global.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/global.c Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,98 @@
+
+#include "value.h"
+#include "static.h"
+#include "vm_config.h"
+
+/*
+
+ GLobal objects are stored in 'mrbc_global' array.
+ 'mrbc_global' array is decending order by sym_id.
+ In case of searching a global object, binary search is used.
+ In case of adding a global object, insertion sort is used.
+
+*/
+
+/* search */
+static int search_global_object(mrb_sym sym_id)
+{
+ int left = 0, right = MAX_GLOBAL_OBJECT_SIZE-1;
+ while( left <= right ){
+ int mid = (left+right)/2;
+ if( mrbc_global[mid].sym_id == sym_id ) return mid;
+ if( mrbc_global[mid].sym_id < sym_id ){
+ right = mid - 1;
+ } else {
+ left = mid + 1;
+ }
+ }
+ return -1;
+}
+
+static int search_const(mrb_sym sym_id) {
+ int left = 0, right = MAX_CONST_COUNT-1;
+ while (left <= right) {
+ int mid = (left + right) / 2;
+ if ( mrbc_const[mid].sym_id == sym_id ) return mid;
+ if ( mrbc_const[mid].sym_id < sym_id ) {
+ right = mid - 1;
+ } else {
+ left = mid + 1;
+ }
+ }
+ return -1;
+}
+
+/* add */
+void global_object_add(mrb_sym sym_id, mrb_object *obj)
+{
+ int index = search_global_object(sym_id);
+ if( index == -1 ){
+ index = MAX_GLOBAL_OBJECT_SIZE-1;
+ while( index > 0 && mrbc_global[index].sym_id < sym_id ){
+ mrbc_global[index] = mrbc_global[index-1];
+ index--;
+ }
+ }
+ mrbc_global[index].sym_id = sym_id;
+ mrbc_global[index].obj = *obj;
+}
+
+void const_add(mrb_sym sym_id, mrb_object *obj)
+{
+ int index = search_const(sym_id);
+ if( index == -1 ){
+ index = MAX_CONST_COUNT-1;
+ while(index > 0 && mrbc_const[index].sym_id < sym_id ){
+ mrbc_const[index] = mrbc_const[index-1];
+ index--;
+ }
+ }
+ mrbc_const[index].sym_id = sym_id;
+ mrbc_const[index].obj = *obj;
+}
+
+/* get */
+mrb_object global_object_get(mrb_sym sym_id)
+{
+ int index = search_global_object(sym_id);
+ if( index >= 0 ){
+ return mrbc_global[index].obj;
+ } else {
+ /* nil */
+ mrb_object obj;
+ obj.tt = MRB_TT_FALSE;
+ return obj;
+ }
+}
+
+mrb_object const_get(mrb_sym sym_id) {
+ int index = search_const(sym_id);
+ if (index >= 0){
+ return mrbc_const[index].obj;
+ } else {
+ mrb_object obj;
+ obj.tt = MRB_TT_FALSE;
+ return obj;
+ }
+}
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/global.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/global.h Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,45 @@
+/*! @file
+ @brief
+ Manage global objects.
+
+ <pre>
+ Copyright (C) 2015 Kyushu Institute of Technology.
+ Copyright (C) 2015 Shimane IT Open-innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+
+ </pre>
+*/
+
+#ifndef MRBC_SRC_GLOBAL_H_
+#define MRBC_SRC_GLOBAL_H_
+
+#include "value.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define OBJECT_WITH_SYMBOL\
+ mrb_sym sym_id;\
+ mrb_object obj
+
+typedef struct GLOBAL_OBJECT {
+ OBJECT_WITH_SYMBOL;
+} mrb_globalobject;
+
+typedef struct CONST_OBJECT {
+ OBJECT_WITH_SYMBOL;
+} mrb_constobject;
+
+void global_object_add(mrb_sym sym_id, mrb_object *obj);
+mrb_object global_object_get(mrb_sym sym_id);
+
+void const_add(mrb_sym sym_id, mrb_object *obj);
+mrb_object const_get(mrb_sym sym_id);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/hal/hal.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/hal/hal.h Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,66 @@
+/*! @file
+ @brief
+ Realtime multitask monitor for mruby/c
+ Hardware abstraction layer
+ for PSoC5LP
+
+ <pre>
+ Copyright (C) 2016 Kyushu Institute of Technology.
+ Copyright (C) 2016 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+ </pre>
+*/
+
+#ifndef MRBC_SRC_HAL_H_
+#define MRBC_SRC_HAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* DON'T USE TIMER */
+#define MRBC_NO_TIMER 1
+
+
+/***** Feature test switches ************************************************/
+/***** System headers *******************************************************/
+
+
+/***** Local headers ********************************************************/
+/***** Constant values ******************************************************/
+/***** Macros ***************************************************************/
+extern void wait_ms(int tm);
+
+#ifndef MRBC_NO_TIMER
+# define hal_init() ((void)0)
+# define hal_enable_irq() CyGlobalIntEnable
+# define hal_disable_irq() CyGlobalIntDisable
+# define hal_idle_cpu() CyPmAltAct(PM_SLEEP_TIME_NONE, \
+ PM_SLEEP_SRC_CTW | PM_SLEEP_SRC_PICU)
+
+#else // MRBC_NO_TIMER
+# define hal_init() ((void)0)
+# define hal_enable_irq() ((void)0)
+# define hal_disable_irq() ((void)0)
+# define hal_idle_cpu() (wait_ms(1), mrbc_tick())
+
+#endif
+
+
+/***** Typedefs *************************************************************/
+/***** Global variables *****************************************************/
+/***** Function prototypes **************************************************/
+int hal_write(int fd, const void *buf, size_t nbytes);
+int hal_flush(int fd);
+
+
+/***** Inline functions *****************************************************/
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif // ifndef MRBC_HAL_H_
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/load.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/load.c Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,282 @@
+/*! @file
+ @brief
+ mruby bytecode loader.
+
+ <pre>
+ Copyright (C) 2015 Kyushu Institute of Technology.
+ Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+
+ </pre>
+*/
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include "vm.h"
+#include "vm_config.h"
+#include "load.h"
+#include "errorcode.h"
+#include "static.h"
+#include "value.h"
+
+
+//================================================================
+/*!@brief
+ Parse header section.
+
+ @param vm A pointer of VM.
+ @param pos A pointer of pointer of RITE header.
+ @return int zero if no error.
+
+ <pre>
+ Structure
+ "RITE" identifier
+ "0003" version
+ 0000 CRC
+ 0000_0000 total size
+ "MATZ" compiler name
+ "0000" compiler version
+ </pre>
+*/
+static int load_header(struct VM *vm, const uint8_t **pos)
+{
+ const uint8_t *p = *pos;
+
+ if( memcmp(p + 4, "0003", 4) != 0 ) {
+ vm->error_code = LOAD_FILE_HEADER_ERROR_VERSION;
+ return -1;
+ }
+
+ /* Ignore CRC */
+
+ /* Ignore size */
+
+ if( memcmp(p + 14, "MATZ", 4) != 0 ) {
+ vm->error_code = LOAD_FILE_HEADER_ERROR_MATZ;
+ return -1;
+ }
+ if( memcmp(p + 18, "0000", 4) != 0 ) {
+ vm->error_code = LOAD_FILE_HEADER_ERROR_VERSION;
+ return -1;
+ }
+
+ *pos += 22;
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Parse IREP section.
+
+ @param vm A pointer of VM.
+ @param pos A pointer of pointer of IREP section.
+ @return int zero if no error.
+
+ <pre>
+ Structure
+ "IREP" section identifier
+ 0000_0000 section size
+ "0000" rite version
+
+ (loop n of child irep bellow)
+ 0000_0000 record size
+ 0000 n of local variable
+ 0000 n of register
+ 0000 n of child irep
+
+ 0000_0000 n of byte code (ISEQ BLOCK)
+ ... byte codes
+
+ 0000_0000 n of pool (POOL BLOCK)
+ (loop n of pool)
+ 00 type
+ 0000 length
+ ... pool data
+
+ 0000_0000 n of symbol (SYMS BLOCK)
+ (loop n of symbol)
+ 0000 length
+ ... symbol data
+ </pre>
+*/
+static int load_irep(struct VM *vm, const uint8_t **pos)
+{
+ const uint8_t *p = *pos;
+ p += 4;
+ int section_size = bin_to_uint32(p);
+ p += 4;
+
+ if( memcmp(p, "0000", 4) != 0 ) {
+ vm->error_code = LOAD_FILE_IREP_ERROR_VERSION;
+ return -1;
+ }
+ p += 4;
+
+ int cnt = 0;
+ while( cnt < section_size ) {
+ cnt += bin_to_uint32(p) + 8;
+ p += 4;
+
+ // new irep
+ mrb_irep *irep = new_irep(vm);
+ if( irep == 0 ) {
+ vm->error_code = LOAD_FILE_IREP_ERROR_ALLOCATION;
+ return -1;
+ }
+
+ // add irep into vm->irep (at tail)
+ // TODO: Optimize this process
+ if( vm->irep == 0 ) {
+ vm->irep = irep;
+ } else {
+ mrb_irep *p = vm->irep;
+ while( p->next != 0 ) {
+ p = p->next;
+ }
+ p->next = irep;
+ }
+ irep->next = 0;
+
+ // nlocals,nregs,rlen
+ irep->nlocals = bin_to_uint16(p); p += 2;
+ irep->nregs = bin_to_uint16(p); p += 2;
+ irep->rlen = bin_to_uint16(p); p += 2;
+ irep->ilen = bin_to_uint32(p); p += 4;
+
+ // padding
+ p += (-(p - *pos + 2) & 0x03); // +2 = (RITE(22) + IREP(12)) & 0x03
+
+ // ISEQ (code) BLOCK
+ irep->code = (uint8_t *)p;
+ p += irep->ilen * 4;
+
+ // POOL BLOCK
+ irep->ptr_to_pool = 0;
+ int plen = bin_to_uint32(p); p += 4;
+ int i;
+ for( i=0 ; i<plen ; i++ ){
+ int tt = (int)*p++;
+ int obj_size = bin_to_uint16(p); p += 2;
+ mrb_object *ptr = mrbc_obj_alloc(vm, MRB_TT_FALSE);
+ if( ptr == 0 ){
+ vm->error_code = LOAD_FILE_IREP_ERROR_ALLOCATION;
+ return -1;
+ }
+ switch( tt ){
+#if MRBC_USE_STRING
+ case 0: { // IREP_TT_STRING
+ ptr->tt = MRB_TT_STRING;
+ ptr->value.str = (char*)p;
+ } break;
+#endif
+ case 1: { // IREP_TT_FIXNUM
+ char buf[obj_size+1];
+ memcpy(buf, p, obj_size);
+ buf[obj_size] = '\0';
+ ptr->tt = MRB_TT_FIXNUM;
+ ptr->value.i = atoi(buf);
+ } break;
+#if MRBC_USE_FLOAT
+ case 2: { // IREP_TT_FLOAT
+ char buf[obj_size+1];
+ memcpy(buf, p, obj_size);
+ buf[obj_size] = '\0';
+ ptr->tt = MRB_TT_FLOAT;
+ ptr->value.d = atof(buf);
+ } break;
+#endif
+ default:
+ break;
+ }
+ if( irep->ptr_to_pool == 0 ){
+ irep->ptr_to_pool = ptr;
+ } else {
+ mrb_object *pp = irep->ptr_to_pool;
+ while( pp->next != 0 ) pp = pp->next;
+ pp->next = ptr;
+ }
+ p += obj_size;
+ }
+
+ // SYMS BLOCK
+ irep->ptr_to_sym = (uint8_t*)p;
+ int slen = bin_to_uint32(p); p += 4;
+ for( i=0 ; i<slen ; i++ ){
+ int s = bin_to_uint16(p); p += 2;
+ p += s+1;
+ }
+ }
+
+ /* TODO: size */
+ *pos += section_size;
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Parse LVAR section.
+
+ @param vm A pointer of VM.
+ @param pos A pointer of pointer of LVAR section.
+ @return int zero if no error.
+*/
+static int load_lvar(struct VM *vm, const uint8_t **pos)
+{
+ const uint8_t *p = *pos;
+
+ /* size */
+ *pos += bin_to_uint32(p+4);
+
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Setup mrb program
+
+ @param vm A pointer of VM.
+ @return int zero if no error.
+*/
+int load_mrb(struct VM *vm)
+{
+ int ret = -1;
+ const uint8_t *pos = vm->mrb;
+
+ if( memcmp(pos, "RITE", 4) == 0 ) {
+ ret = load_header(vm, &pos);
+ }
+ while( ret == 0 ) {
+ if( memcmp(pos, "IREP", 4) == 0 ) {
+ ret = load_irep(vm, &pos);
+ }
+ else if( memcmp(pos, "LVAR", 4) == 0 ) {
+ ret = load_lvar(vm, &pos);
+ }
+ else if( memcmp(pos, "END\0", 4) == 0 ) {
+ break;
+ }
+ }
+
+ return ret;
+}
+
+
+//================================================================
+/*!@brief
+
+
+ @param vm A pointer of VM.
+ @param ptr A pointer of RITE (.mrb) code.
+
+*/
+int loca_mrb_array(struct VM *vm, const uint8_t *ptr)
+{
+ vm->mrb = ptr;
+ return load_mrb(vm);
+}
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/load.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/load.h Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,32 @@
+/*! @file
+ @brief
+ mruby bytecode loader.
+
+ <pre>
+ Copyright (C) 2015 Kyushu Institute of Technology.
+ Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+
+ </pre>
+*/
+
+#ifndef MRBC_SRC_LOAD_H_
+#define MRBC_SRC_LOAD_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+int loca_mrb_array(struct VM *vm, const uint8_t *ptr);
+int load_mrb(struct VM *vm);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/mrubyc.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mrubyc/mrubyc.h Wed Feb 15 01:03:35 2017 +0000 @@ -0,0 +1,27 @@ +/*! @file + @brief + Include at once the necessary header files for user program. + + <pre> + Copyright (C) 2015-2016 Kyushu Institute of Technology. + Copyright (C) 2015-2016 Shimane IT Open-Innovation Center. + + This file is distributed under BSD 3-Clause License. + + </pre> +*/ + +#ifndef MRBC_SRC_MRUBYC_H_ +#define MRBC_SRC_MRUBYC_H_ + +#include "errorcode.h" +#include "vm.h" +#include "value.h" +#include "static.h" +#include "alloc.h" +#include "class.h" +#include "load.h" +#include "rrt0.h" + +#endif +
diff -r 000000000000 -r 33feccbba3ff mrubyc/opcode.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/opcode.h Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,102 @@
+/*! @file
+ @brief
+
+
+ <pre>
+ Copyright (C) 2015 Kyushu Institute of Technology.
+ Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+
+
+ </pre>
+*/
+
+#ifndef MRBC_SRC_OPCODE_H_
+#define MRBC_SRC_OPCODE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define GET_OPCODE(code) ((code) & 0x7f)
+#define GETARG_A(code) (((code) >> 23) & 0x1ff)
+#define GETARG_B(code) (((code) >> 14) & 0x1ff)
+#define GETARG_C(code) (((code) >> 7) & 0x7f)
+#define GETARG_Ax(code) (((code) >> 7) & 0x1ffffff)
+
+#define GETARG_b(code) GETARG_UNPACK_b(code,14,2)
+
+#define GETARG_UNPACK_b(i,n1,n2) ((((code)) >> (7+(n2))) & (((1<<(n1))-1)))
+
+
+#define MAXARG_Bx (0xffff)
+#define MAXARG_sBx (MAXARG_Bx>>1)
+#define GETARG_Bx(code) (((code) >> 7) & 0xffff)
+#define GETARG_sBx(code) (GETARG_Bx(code)-MAXARG_sBx)
+#define GETARG_C(code) (((code) >> 7) & 0x7f)
+
+
+//================================================================
+/*!@brief
+
+*/
+enum OPCODE {
+ OP_NOP = 0x00,
+ OP_MOVE = 0x01,
+ OP_LOADL = 0x02,
+ OP_LOADI = 0x03,
+ OP_LOADSYM = 0x04,
+ OP_LOADNIL = 0x05,
+ OP_LOADSELF = 0x06,
+ OP_LOADT = 0x07,
+ OP_LOADF = 0x08,
+ OP_GETGLOBAL = 0x09,
+ OP_SETGLOBAL = 0x0a,
+
+ OP_GETCONST = 0x11,
+ OP_SETCONST = 0x12,
+
+ OP_JMP = 0x17,
+ OP_JMPIF = 0x18,
+ OP_JMPNOT = 0x19,
+ OP_SEND = 0x20,
+
+ OP_ENTER = 0x26,
+
+ OP_RETURN = 0x29,
+
+ OP_ADD = 0x2c,
+ OP_ADDI = 0x2d,
+ OP_SUB = 0x2e,
+ OP_SUBI = 0x2f,
+ OP_MUL = 0x30,
+ OP_DIV = 0x31,
+ OP_EQ = 0x32,
+ OP_LT = 0x33,
+ OP_LE = 0x34,
+ OP_GT = 0x35,
+ OP_GE = 0x36,
+ OP_ARRAY = 0x37,
+
+ OP_STRING = 0x3d,
+
+ OP_HASH = 0x3f,
+ OP_LAMBDA = 0x40,
+ OP_RANGE = 0x41,
+
+ OP_CLASS = 0x43,
+
+ OP_METHOD = 0x46,
+
+ OP_TCLASS = 0x48,
+
+ OP_STOP = 0x4a,
+};
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/rrt0.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/rrt0.c Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,574 @@
+/*! @file
+ @brief
+ Realtime multitask monitor for mruby/c
+
+ <pre>
+ Copyright (C) 2016 Kyushu Institute of Technology.
+ Copyright (C) 2016 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+ </pre>
+*/
+
+/***** Feature test switches ************************************************/
+/***** System headers *******************************************************/
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+
+
+/***** Local headers ********************************************************/
+#include "alloc.h"
+#include "static.h"
+#include "load.h"
+#include "class.h"
+#include "vm.h"
+#include "rrt0.h"
+#include "hal/hal.h"
+
+
+/***** Constat values *******************************************************/
+const int TIMESLICE_TICK = 10; // 10 * 1ms(HardwareTimer) 255 max
+
+
+/***** Macros ***************************************************************/
+/***** Typedefs *************************************************************/
+/***** Function prototypes **************************************************/
+/***** Local variables ******************************************************/
+static MrbcTcb *q_domant_;
+static MrbcTcb *q_ready_;
+static MrbcTcb *q_waiting_;
+static MrbcTcb *q_suspended_;
+static volatile uint32_t tick_;
+
+
+/***** Global variables *****************************************************/
+/***** Signal catching functions ********************************************/
+/***** Local functions ******************************************************/
+
+//================================================================
+/*! Insert to task queue
+
+ @param Pointer of target TCB
+
+ 引数で指定されたタスク(TCB)を、状態別Queueに入れる。
+ TCBはフリーの状態でなければならない。(別なQueueに入っていてはならない)
+ Queueはpriority_preemption順にソート済みとなる。
+ 挿入するTCBとQueueに同じpriority_preemption値がある場合は、同値の最後に挿入される。
+
+ */
+static void q_insert_task(MrbcTcb *p_tcb)
+{
+ MrbcTcb **pp_q;
+
+ switch( p_tcb->state ) {
+ case TASKSTATE_DOMANT: pp_q = &q_domant_; break;
+ case TASKSTATE_READY:
+ case TASKSTATE_RUNNING: pp_q = &q_ready_; break;
+ case TASKSTATE_WAITING: pp_q = &q_waiting_; break;
+ case TASKSTATE_SUSPENDED: pp_q = &q_suspended_; break;
+ default:
+ assert(!"Wrong task state.");
+ return;
+ }
+
+ // case insert on top.
+ if((*pp_q == NULL) ||
+ (p_tcb->priority_preemption < (*pp_q)->priority_preemption)) {
+ p_tcb->next = *pp_q;
+ *pp_q = p_tcb;
+ assert(p_tcb->next != p_tcb);
+ return;
+ }
+
+ // find insert point in sorted linked list.
+ MrbcTcb *p = *pp_q;
+ while( 1 ) {
+ if((p->next == NULL) ||
+ (p_tcb->priority_preemption < p->next->priority_preemption)) {
+ p_tcb->next = p->next;
+ p->next = p_tcb;
+ assert(p->next != p);
+ return;
+ }
+
+ p = p->next;
+ }
+}
+
+
+//================================================================
+/*! Delete from task queue
+
+ @param Pointer of target TCB
+
+ Queueからタスク(TCB)を取り除く。
+
+ */
+static void q_delete_task(MrbcTcb *p_tcb)
+{
+ MrbcTcb **pp_q;
+
+ switch( p_tcb->state ) {
+ case TASKSTATE_DOMANT: pp_q = &q_domant_; break;
+ case TASKSTATE_READY:
+ case TASKSTATE_RUNNING: pp_q = &q_ready_; break;
+ case TASKSTATE_WAITING: pp_q = &q_waiting_; break;
+ case TASKSTATE_SUSPENDED: pp_q = &q_suspended_; break;
+ default:
+ assert(!"Wrong task state.");
+ return;
+ }
+
+ if( *pp_q == NULL ) return;
+ if( *pp_q == p_tcb ) {
+ *pp_q = p_tcb->next;
+ p_tcb->next = NULL;
+ return;
+ }
+
+ MrbcTcb *p = *pp_q;
+ while( p ) {
+ if( p->next == p_tcb ) {
+ p->next = p_tcb->next;
+ p_tcb->next = NULL;
+ return;
+ }
+
+ p = p->next;
+ }
+}
+
+
+//================================================================
+/*! Find requested task
+
+ @param Pointer of vm
+ @return Pointer of MrbcTcb. zero is not found.
+ */
+static inline MrbcTcb* find_requested_task(mrb_vm *vm)
+{
+ MrbcTcb *tcb;
+
+ for( tcb = q_ready_; tcb != NULL; tcb = tcb->next ) {
+ if( tcb->vm == vm ) break;
+ }
+
+ return tcb;
+}
+
+
+//================================================================
+/*! 一定時間停止(cruby互換)
+
+*/
+static void c_sleep(mrb_vm *vm, mrb_value *v)
+{
+ MrbcTcb *tcb = find_requested_task(vm);
+
+ if( tcb == NULL ) return;
+
+ switch( v[1].tt ) {
+ case MRB_TT_FIXNUM:
+ mrbc_sleep_ms(tcb, GET_INT_ARG(0) * 1000);
+ break;
+
+ case MRB_TT_FLOAT:
+ mrbc_sleep_ms(tcb, (uint32_t)(GET_FLOAT_ARG(0) * 1000));
+ break;
+
+ default:
+
+ // TODO 引数なしの場合は永久停止
+ break;
+ }
+}
+
+
+//================================================================
+/*! 一定時間停止(ms単位)
+
+*/
+static void c_sleep_ms(mrb_vm *vm, mrb_value *v)
+{
+ MrbcTcb *tcb = find_requested_task(vm);
+
+ if( tcb == NULL ) return;
+
+ mrbc_sleep_ms(tcb, GET_INT_ARG(0));
+}
+
+
+//================================================================
+/*! 実行権を手放す
+
+*/
+static void c_relinquish(mrb_vm *vm, mrb_value *v)
+{
+ MrbcTcb *tcb = find_requested_task(vm);
+
+ if( tcb == NULL ) return;
+
+ mrbc_relinquish(tcb);
+}
+
+
+//================================================================
+/*! プライオリティー変更
+
+*/
+static void c_change_priority(mrb_vm *vm, mrb_value *v)
+{
+ MrbcTcb *tcb = find_requested_task(vm);
+
+ if( tcb == NULL ) return;
+
+ mrbc_change_priority(tcb, GET_INT_ARG(0));
+}
+
+
+//================================================================
+/*! 実行停止
+
+*/
+static void c_suspend_task(mrb_vm *vm, mrb_value *v)
+{
+ MrbcTcb *tcb = find_requested_task(vm);
+
+ if( tcb == NULL ) return;
+
+ mrbc_suspend_task(tcb);
+}
+
+
+//================================================================
+/*! 実行再開
+
+*/
+static void c_resume_task(mrb_vm *vm, mrb_value *v)
+{
+ MrbcTcb *tcb = find_requested_task(vm);
+
+ if( tcb == NULL ) return;
+
+ // TODO: 未デバグ。引数で与えられたTCBのタスクを実行再開する。
+ mrbc_resume_task(tcb);
+}
+
+
+//================================================================
+/*! TCBを得る
+
+*/
+static void c_get_tcb(mrb_vm *vm, mrb_value *v)
+{
+ MrbcTcb *tcb = find_requested_task(vm);
+
+ if( tcb == NULL ) return;
+
+ // TODO: 未実装。TCBポインタをオブジェクトとして返す。
+}
+
+
+/***** Global functions *****************************************************/
+
+//================================================================
+/*! Tick timer interrupt handler.
+
+*/
+void mrbc_tick(void)
+{
+ MrbcTcb *tcb;
+ int flag_preemption = 0;
+
+ tick_++;
+
+ // 実行中タスクのタイムスライス値を減らす
+ tcb = q_ready_;
+ if((tcb != NULL) &&
+ (tcb->state == TASKSTATE_RUNNING) &&
+ (tcb->timeslice > 0)) {
+ tcb->timeslice--;
+ if( tcb->timeslice == 0 ) tcb->vm->flag_preemption = 1;
+ }
+
+ // 待ちタスクキューから、ウェイクアップすべきタスクを探す
+ tcb = q_waiting_;
+ while( tcb != NULL ) {
+ MrbcTcb *t = tcb;
+ tcb = tcb->next;
+
+ if( t->wakeup_tick == tick_ ) {
+ q_delete_task(t);
+ t->state = TASKSTATE_READY;
+ t->timeslice = TIMESLICE_TICK;
+ q_insert_task(t);
+ flag_preemption = 1;
+ }
+ }
+
+ if( flag_preemption ) {
+ tcb = q_ready_;
+ while( tcb != NULL ) {
+ if( tcb->state == TASKSTATE_RUNNING ) tcb->vm->flag_preemption = 1;
+ tcb = tcb->next;
+ }
+ }
+}
+
+
+//================================================================
+/*! initialize
+
+*/
+void mrbc_init(void)
+{
+ mrbc_init_alloc();
+ init_static();
+ hal_init();
+
+
+ // TODO 関数呼び出しが、c_XXX => mrbc_XXX の daisy chain になっている。
+ // 不要な複雑さかもしれない。要リファクタリング。
+ mrbc_define_method(0, mrbc_class_object, "sleep", c_sleep);
+ mrbc_define_method(0, mrbc_class_object, "sleep_ms", c_sleep_ms);
+ mrbc_define_method(0, mrbc_class_object, "relinquish", c_relinquish);
+ mrbc_define_method(0, mrbc_class_object, "change_priority", c_change_priority);
+ mrbc_define_method(0, mrbc_class_object, "suspend_task", c_suspend_task);
+ mrbc_define_method(0, mrbc_class_object, "resume_task", c_resume_task);
+}
+
+
+//================================================================
+/*! specify running VM code.
+
+ @param vm_code pointer of VM byte code.
+ @param tcb Task control block with parameter, or NULL.
+ @retval Pointer of MrbcTcb.
+ @retval NULL is error.
+
+*/
+MrbcTcb* mrbc_create_task(const uint8_t *vm_code, MrbcTcb *tcb)
+{
+ // allocate Task Control Block
+ if( tcb == NULL ) {
+ tcb = (MrbcTcb*)mrbc_raw_alloc( sizeof(MrbcTcb) );
+ if( tcb == NULL ) return NULL; // ENOMEM
+
+ static const MrbcTcb init_val = MRBC_TCB_INITIALIZER;
+ *tcb = init_val;
+ }
+ tcb->timeslice = TIMESLICE_TICK;
+ tcb->priority_preemption = tcb->priority;
+
+ // assign VM on TCB
+ if( tcb->state != TASKSTATE_DOMANT ) {
+ tcb->vm = vm_open();
+ if( !tcb->vm ) return 0; // error. can't open VM.
+ // NOTE: memory leak MrbcTcb. but ignore.
+
+ loca_mrb_array(tcb->vm, vm_code);
+ vm_boot(tcb->vm);
+ }
+
+ hal_disable_irq();
+ q_insert_task(tcb);
+ hal_enable_irq();
+
+ return tcb;
+}
+
+
+//================================================================
+/*! execute
+
+*/
+int mrbc_run(void)
+{
+ while( 1 ) {
+ MrbcTcb *tcb = q_ready_;
+ if( tcb == NULL ) {
+ // 実行すべきタスクなし
+ hal_idle_cpu();
+ continue;
+ }
+
+ // 実行開始
+ tcb->state = TASKSTATE_RUNNING;
+ int res = 0;
+
+#ifndef MRBC_NO_TIMER
+ tcb->vm->flag_preemption = 0;
+ res = vm_run(tcb->vm);
+
+#else
+ while( tcb->timeslice > 0 ) {
+ tcb->vm->flag_preemption = 1;
+ res = vm_run(tcb->vm);
+ tcb->timeslice--;
+ if( res < 0 ) break;
+ if( tcb->state != TASKSTATE_RUNNING ) break;
+ }
+ mrbc_tick();
+#endif /* ifndef MRBC_NO_TIMER */
+
+ // タスク終了?
+ if( res < 0 ) {
+ hal_disable_irq();
+ q_delete_task(tcb);
+ tcb->state = TASKSTATE_DOMANT;
+ q_insert_task(tcb);
+ hal_enable_irq();
+ vm_close(tcb->vm);
+ tcb->vm = 0;
+
+ if( q_ready_ == NULL && q_waiting_ == NULL &&
+ q_suspended_ == NULL ) break;
+ continue;
+ }
+
+ // タスク切り替え
+ hal_disable_irq();
+ if( tcb->state == TASKSTATE_RUNNING ) {
+ tcb->state = TASKSTATE_READY;
+
+ // タイムスライス終了?
+ if( tcb->timeslice == 0 ) {
+ q_delete_task(tcb);
+ tcb->timeslice = TIMESLICE_TICK;
+ q_insert_task(tcb); // insert task on queue last.
+ }
+ }
+ hal_enable_irq();
+ }
+
+ return 0;
+}
+
+
+//================================================================
+/*! 実行一時停止
+
+*/
+void mrbc_sleep_ms(MrbcTcb *tcb, uint32_t ms)
+{
+ hal_disable_irq();
+ q_delete_task(tcb);
+ tcb->timeslice = 0;
+ tcb->state = TASKSTATE_WAITING;
+ tcb->wakeup_tick = tick_ + ms;
+ q_insert_task(tcb);
+ hal_enable_irq();
+
+ tcb->vm->flag_preemption = 1;
+}
+
+
+//================================================================
+/*! 実行権を手放す
+
+*/
+void mrbc_relinquish(MrbcTcb *tcb)
+{
+ tcb->timeslice = 0;
+ tcb->vm->flag_preemption = 1;
+}
+
+
+//================================================================
+/*! プライオリティーの変更
+ TODO: No check, yet.
+*/
+void mrbc_change_priority(MrbcTcb *tcb, int priority)
+{
+ tcb->priority = (uint8_t)priority;
+ tcb->priority_preemption = (uint8_t)priority;
+ tcb->timeslice = 0;
+ tcb->vm->flag_preemption = 1;
+}
+
+
+//================================================================
+/*! 実行停止
+
+*/
+void mrbc_suspend_task(MrbcTcb *tcb)
+{
+ hal_disable_irq();
+ q_delete_task(tcb);
+ tcb->state = TASKSTATE_SUSPENDED;
+ q_insert_task(tcb);
+ hal_enable_irq();
+
+ tcb->vm->flag_preemption = 1;
+}
+
+
+//================================================================
+/*! 実行再開
+
+*/
+void mrbc_resume_task(MrbcTcb *tcb)
+{
+ hal_disable_irq();
+
+ MrbcTcb *t = q_ready_;
+ while( t != NULL ) {
+ if( t->state == TASKSTATE_RUNNING ) t->vm->flag_preemption = 1;
+ t = t->next;
+ }
+
+ q_delete_task(tcb);
+ tcb->state = TASKSTATE_READY;
+ q_insert_task(tcb);
+ hal_enable_irq();
+}
+
+
+#ifdef MRBC_DEBUG
+#include "console.h"
+
+//================================================================
+/*! DEBUG print queue
+
+ */
+void pq(MrbcTcb *p_tcb)
+{
+ MrbcTcb *p;
+
+ p = p_tcb;
+ while( p != NULL ) {
+ console_printf("%08x ", (int)((uint64_t)p & 0xffffffff));
+ p = p->next;
+ }
+ console_printf("\n");
+
+ p = p_tcb;
+ while( p != NULL ) {
+ console_printf(" pri: %2d ", p->priority_preemption);
+ p = p->next;
+ }
+ console_printf("\n");
+
+ p = p_tcb;
+ while( p != NULL ) {
+ console_printf(" nx:%04x ", (int)((uint64_t)p->next & 0xffff));
+ p = p->next;
+ }
+ console_printf("\n");
+}
+
+
+void pqall(void)
+{
+ // console_printf("<<<<< DOMANT >>>>>\n");
+ // pq(q_domant_);
+ console_printf("<<<<< READY >>>>>\n");
+ pq(q_ready_);
+ console_printf("<<<<< WAITING >>>>>\n");
+ pq(q_waiting_);
+ console_printf("<<<<< SUSPENDED >>>>>\n");
+ pq(q_suspended_);
+}
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/rrt0.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/rrt0.h Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,83 @@
+/*! @file
+ @brief
+ Realtime multitask monitor for mruby/c
+
+ <pre>
+ Copyright (C) 2016 Kyushu Institute of Technology.
+ Copyright (C) 2016 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+ </pre>
+*/
+
+#ifndef MRBC_SRC_RRT0_H_
+#define MRBC_SRC_RRT0_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***** Feature test switches ************************************************/
+/***** System headers *******************************************************/
+#include <stdint.h>
+
+/***** Local headers ********************************************************/
+/***** Constant values ******************************************************/
+
+//================================================
+/*!@brief
+ Task state
+*/
+enum MrbcTaskState {
+ TASKSTATE_DOMANT = 0x00,
+ TASKSTATE_READY = 0x01,
+ TASKSTATE_RUNNING = 0x03,
+ TASKSTATE_WAITING = 0x04,
+ TASKSTATE_SUSPENDED = 0x08,
+};
+
+
+/***** Macros ***************************************************************/
+/***** Typedefs *************************************************************/
+
+//================================================
+/*!@brief
+ Task control block
+*/
+struct VM;
+typedef volatile struct st_MrbcTcb {
+ volatile struct st_MrbcTcb *next;
+ struct VM *vm;
+ uint8_t priority;
+ uint8_t priority_preemption;
+ uint8_t timeslice;
+ uint8_t state; //!< enum MrbcTaskState
+ union {
+ uint32_t wakeup_tick;
+ };
+} MrbcTcb;
+
+#define MRBC_TCB_INITIALIZER { 0, 0, 128, 128, 0, TASKSTATE_READY }
+
+
+/***** Global variables *****************************************************/
+/***** Function prototypes **************************************************/
+void mrbc_tick(void);
+void mrbc_init(void);
+MrbcTcb *mrbc_create_task(const uint8_t *vm_code, MrbcTcb *tcb);
+int mrbc_run(void);
+void mrbc_sleep_ms(MrbcTcb *tcb, uint32_t ms);
+void mrbc_relinquish(MrbcTcb *tcb);
+void mrbc_change_priority(MrbcTcb *tcb, int priority);
+void mrbc_suspend_task(MrbcTcb *tcb);
+void mrbc_resume_task(MrbcTcb *tcb);
+
+
+/***** Inline functions *****************************************************/
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif // ifndef MRBC_RRT0_H_
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/static.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/static.c Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,69 @@
+/*! @file
+ @brief
+ Declare static data.
+
+ <pre>
+ Copyright (C) 2015-2016 Kyushu Institute of Technology.
+ Copyright (C) 2015-2016 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+ </pre>
+*/
+
+#include "static.h"
+#include "vm_config.h"
+#include "class.h"
+#include "symbol.h"
+
+/* Static Variables */
+/* VM contains regs, stack, PC, and so on */
+mrb_vm mrbc_vm[MAX_VM_COUNT];
+
+//static mrb_object mrbc_object[MAX_OBJECT_COUNT];
+//mrb_object *mrbc_pool_object;
+
+mrb_constobject mrbc_const[MAX_CONST_COUNT];
+
+mrb_globalobject mrbc_global[MAX_GLOBAL_OBJECT_SIZE];
+
+/* Class Tree */
+mrb_class *mrbc_class_object;
+
+/* Classes */
+mrb_class *mrbc_class_false;
+mrb_class *mrbc_class_true;
+mrb_class *mrbc_class_nil;
+mrb_class *mrbc_class_array;
+mrb_class *mrbc_class_fixnum;
+mrb_class *mrbc_class_symbol;
+#if MRBC_USE_FLOAT
+mrb_class *mrbc_class_float;
+#endif
+#if MRBC_USE_STRING
+mrb_class *mrbc_class_string;
+#endif
+mrb_class *mrbc_class_range;
+mrb_class *mrbc_class_hash;
+
+void init_static(void)
+{
+ int i;
+
+ for( i=0 ; i<MAX_VM_COUNT ; i++ ){
+ mrbc_vm[i].vm_id = i+1;
+ mrbc_vm[i].priority = -1;
+ }
+
+ /* global objects */
+ for( i=0 ; i<MAX_GLOBAL_OBJECT_SIZE ; i++ ){
+ mrbc_global[i].sym_id = -1;
+ }
+
+ for( i=0 ; i<MAX_CONST_COUNT; i++ ){
+ mrbc_const[i].sym_id = -1;
+ }
+
+ /* init class */
+ mrbc_init_class();
+}
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/static.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/static.h Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,58 @@
+/*! @file
+ @brief
+ Declare static data.
+
+ <pre>
+ Copyright (C) 2015-2016 Kyushu Institute of Technology.
+ Copyright (C) 2015-2016 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+ </pre>
+*/
+
+#ifndef MRBC_SRC_STATIC_H_
+#define MRBC_SRC_STATIC_H_
+
+#include "vm.h"
+#include "global.h"
+#include "value.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* VM */
+extern mrb_vm mrbc_vm[];
+
+/* Object */
+//extern mrb_object *mrbc_pool_object;
+
+
+/* Class Tree */
+extern mrb_class *mrbc_class_object;
+
+extern mrb_class *mrbc_class_false;
+extern mrb_class *mrbc_class_true;
+extern mrb_class *mrbc_class_nil;
+extern mrb_class *mrbc_class_array;
+extern mrb_class *mrbc_class_fixnum;
+extern mrb_class *mrbc_class_float;
+extern mrb_class *mrbc_class_string;
+extern mrb_class *mrbc_class_symbol;
+extern mrb_class *mrbc_class_range;
+extern mrb_class *mrbc_class_hash;
+
+
+extern mrb_constobject mrbc_const[];
+/* Global Objects */
+extern mrb_globalobject mrbc_global[];
+
+void init_static(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/symbol.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/symbol.c Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,123 @@
+/*! @file
+ @brief
+ Symbol
+
+ <pre>
+ Copyright (C) 2015-2016 Kyushu Institute of Technology.
+ Copyright (C) 2015-2016 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+
+ </pre>
+*/
+
+#include <string.h>
+#include "symbol.h"
+#include "console.h"
+
+
+struct SYM_INDEX {
+ uint16_t hash; //!< hash value, returned by calc_hash().
+ char *pos; //!< point to the symbol string. maybe in sym_table[].
+};
+
+
+static struct SYM_INDEX sym_index[MAX_SYMBOLS_COUNT];
+static int sym_index_pos; // point to the last(free) sym_index array.
+static char sym_table[MAX_SYMBOLS_SIZE]; // symbol string table.
+static char *sym_table_pos = sym_table; // point to the last(free) sym_table.
+
+
+//================================================================
+/*! Caliculate hash value.
+
+ @param str Target string.
+ @return uint16_t Hash value.
+*/
+static uint16_t calc_hash(const char *str)
+{
+ uint16_t h = 0;
+
+ while( *str != '\0' ) {
+ h = h * 37 + *str;
+ str++;
+ }
+ return h;
+}
+
+
+//================================================================
+/*! Add symbol to symbol table.
+
+ @param str Target string.
+ @return mrb_sym Symbol value.
+ @retval -1 If error occurred.
+*/
+mrb_sym add_sym(const char *str)
+{
+ mrb_sym sym_id = str_to_symid(str);
+
+ if( sym_id < 0 ) {
+ // check overflow.
+ if( sym_index_pos >= MAX_SYMBOLS_COUNT ) {
+ console_printf( "Overflow %s '%s'\n", "MAX_SYMBOLS_COUNT", str );
+ return -1;
+ }
+ int len = strlen(str);
+ if( len == 0 ) return -1;
+ len++;
+ if( len > (MAX_SYMBOLS_SIZE - (sym_table_pos - sym_table)) ) {
+ console_printf( "Overflow %s '%s'\n", "MAX_SYMBOLS_SIZE", str );
+ return -1;
+ }
+
+ // ok! go.
+ sym_index[sym_index_pos].hash = calc_hash(str);
+ sym_index[sym_index_pos].pos = sym_table_pos;
+ sym_id = sym_index_pos;
+ sym_index_pos++;
+ memcpy(sym_table_pos, str, len);
+ sym_table_pos += len;
+ }
+
+ return sym_id;
+}
+
+
+//================================================================
+/*! Convert string to symbol value.
+
+ @param str Target string.
+ @return mrb_sym Symbol value.
+*/
+mrb_sym str_to_symid(const char *str)
+{
+ uint16_t h = calc_hash(str);
+ int i;
+
+ for( i = 0; i < sym_index_pos; i++ ) {
+ if( sym_index[i].hash == h ) {
+ if( strcmp(str, sym_index[i].pos) == 0 ) {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
+
+//================================================================
+/*! Convert symbol value to string.
+
+ @param mrb_sym Symbol value.
+ @return const char* String.
+ @retval NULL Invalid sym_id was given.
+*/
+const char* symid_to_str(mrb_sym sym_id)
+{
+ if( sym_id < 0 ) return NULL;
+ if( sym_id >= sym_index_pos ) return NULL;
+
+ return sym_index[sym_id].pos;
+}
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/symbol.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/symbol.h Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,32 @@
+/*! @file
+ @brief
+ Symbol
+
+ <pre>
+ Copyright (C) 2015-2016 Kyushu Institute of Technology.
+ Copyright (C) 2015-2016 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+
+ </pre>
+*/
+
+#ifndef MRBC_SRC_SYMBOL_H_
+#define MRBC_SRC_SYMBOL_H_
+
+#include "value.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+mrb_sym add_sym(const char *str);
+mrb_sym str_to_symid(const char *str);
+const char* symid_to_str(mrb_sym sym_id);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/value.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/value.c Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,91 @@
+#include <stdint.h>
+#include <string.h>
+#include "value.h"
+#include "static.h"
+#include "symbol.h"
+#include "alloc.h"
+#include "vm.h"
+
+mrb_object *mrbc_obj_alloc(mrb_vm *vm, mrb_vtype tt)
+{
+ mrb_object *ptr = (mrb_object *)mrbc_alloc(vm, sizeof(mrb_object));
+ if( ptr ){
+ ptr->tt = tt;
+ ptr->next = 0;
+ }
+ return ptr;
+}
+
+mrb_class *mrbc_class_alloc(mrb_vm *vm, const char *name, mrb_class *super)
+{
+ mrb_class *ptr = (mrb_class *)mrbc_alloc(vm, sizeof(mrb_class));
+ if( ptr ){
+ ptr->tt = MRB_TT_CLASS;
+ ptr->super = super;
+ ptr->name = add_sym(name);
+ ptr->procs = 0;
+ ptr->next = 0;
+ }
+ return ptr;
+}
+
+mrb_proc *mrbc_rproc_alloc(mrb_vm *vm, const char *name)
+{
+ mrb_proc *ptr = (mrb_proc *)mrbc_alloc(vm, sizeof(mrb_proc));
+ if( ptr ) {
+ ptr->sym_id = add_sym(name);
+ ptr->next = 0;
+ }
+ return ptr;
+}
+
+mrb_proc *mrbc_rproc_alloc_to_class(mrb_vm *vm, const char *name, mrb_class *cls)
+{
+ mrb_proc *rproc = mrbc_rproc_alloc(vm, name);
+ if( rproc != 0 ){
+ rproc->next = cls->procs;
+ cls->procs = rproc;
+ }
+ return rproc;
+}
+
+
+// EQ? two objects
+// EQ: return true
+// NEQ: return false
+int mrbc_eq(mrb_value *v1, mrb_value *v2)
+{
+ // TT_XXX is different
+ if( v1->tt != v2->tt ) return 0;
+ // check value
+ switch( v1->tt ){
+ case MRB_TT_TRUE:
+ case MRB_TT_FALSE:
+ case MRB_TT_NIL:
+ return 1;
+ case MRB_TT_FIXNUM:
+ case MRB_TT_SYMBOL:
+ return v1->value.i == v2->value.i;
+ case MRB_TT_FLOAT:
+ return v1->value.d == v2->value.d;
+ case MRB_TT_STRING:
+ return !strcmp(v1->value.str, v2->value.str);
+ case MRB_TT_ARRAY: {
+ mrb_value *array1 = v1->value.obj;
+ mrb_value *array2 = v2->value.obj;
+ int i, len = array1[0].value.i;
+ if( len != array2[0].value.i ) return 0;
+ for( i=1 ; i<=len ; i++ ){
+ if( !mrbc_eq(array1+i, array2+i) ) break;
+ }
+ if( i > len ){
+ return 1;
+ } else {
+ return 0;
+ }
+ } break;
+ default:
+ return 0;
+ }
+}
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/value.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/value.h Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,156 @@
+/*! @file
+ @brief
+
+
+ <pre>
+ Copyright (C) 2015 Kyushu Institute of Technology.
+ Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+
+
+ </pre>
+*/
+
+#ifndef MRBC_SRC_VALUE_H_
+#define MRBC_SRC_VALUE_H_
+
+#include <stdint.h>
+#include "vm_config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+// mrb types
+//typedef float mrb_float;
+typedef int32_t mrb_int;
+typedef int32_t mrb_sym;
+
+/* aspec access ? */
+#define MRB_ASPEC_REQ(a) (((a) >> 18) & 0x1f)
+#define MRB_ASPEC_OPT(a) (((a) >> 13) & 0x1f)
+#define MRB_ASPEC_REST(a) (((a) >> 12) & 0x1)
+#define MRB_ASPEC_POST(a) (((a) >> 7) & 0x1f)
+
+// #define GET_TYPE(v) ((v).tt)
+#define IS_FIXNUM(v) (((v).tt)==MRB_TT_FIXNUM)
+
+#pragma pack(2)
+
+//================================================================
+/*!@brief
+
+*/
+typedef enum {
+ /* internal use */
+ MRB_TT_HANDLE = -1,
+ /* primitive */
+ MRB_TT_EMPTY = 0,
+ MRB_TT_TRUE,
+ MRB_TT_FALSE,
+ MRB_TT_NIL,
+ MRB_TT_FIXNUM,
+ MRB_TT_FLOAT,
+ MRB_TT_SYMBOL,
+ /* non-primitive */
+ MRB_TT_OBJECT = 20,
+ MRB_TT_CLASS,
+ MRB_TT_PROC,
+ MRB_TT_ARRAY,
+ MRB_TT_STRING,
+ MRB_TT_RANGE,
+ MRB_TT_HASH,
+
+} mrb_vtype;
+
+
+//================================================================
+/*!@brief
+
+*/
+typedef struct RClass {
+ struct RClass *next; // linked list
+ mrb_vtype tt:8;
+ mrb_sym name; // class name
+ struct RClass *super; // mrbc_class[super]
+ struct RProc *procs; // mrbc_proc[rprocs], linked list
+} mrb_class;
+
+
+//================================================================
+/*!@brief
+
+*/
+typedef struct RObject {
+ struct RObject *next;
+ mrb_vtype tt;
+ union {
+ int32_t i; // MRB_TT_FIXNUM
+ struct RObject *obj; // MRB_TT_OBJECT : link to object
+ struct RClass *cls; // MRB_TT_CLASS : link to class
+ struct RProc *proc; // MRB_TT_PROC : link to proc
+ struct RObject *array; // MRB_TT_ARRAY : array of objects
+ struct RObject *range; // MRB_TT_RANGE : link to range
+ double d; // MRB_TT_FLOAT : float
+ char *str; // MRB_TT_STRING : C-string
+ } value;
+} mrb_object;
+typedef struct RObject mrb_value;
+
+
+struct VM;
+typedef void (*mrb_func_t)(struct VM *vm, mrb_value *v);
+
+
+
+//================================================================
+/*!@brief
+
+*/
+typedef struct RProc {
+ struct RProc *next;
+ unsigned int c_func:1; // 0:IREP, 1:C Func
+ int16_t sym_id;
+ union {
+ struct IREP *irep;
+ mrb_func_t func;
+ } func;
+} mrb_proc;
+
+
+// alloc one object
+mrb_object *mrbc_obj_alloc(struct VM *vm, mrb_vtype tt);
+
+// alloc one class
+mrb_class *mrbc_class_alloc(struct VM *vm, const char *name, mrb_class *super);
+
+
+// alloc one RProc
+mrb_proc *mrbc_rproc_alloc(struct VM *vm, const char *name);
+mrb_proc *mrbc_rproc_alloc_to_class(struct VM *vm, const char *name, mrb_class *cls);
+
+// EQ two objects
+int mrbc_eq(mrb_value *v1, mrb_value *v2);
+
+
+// for C call
+#define SET_INT_RETURN(n) {v[0].tt=MRB_TT_FIXNUM;v[0].value.i=(n);}
+#define SET_NIL_RETURN() v[0].tt=MRB_TT_NIL
+#define SET_FALSE_RETURN() v[0].tt=MRB_TT_FALSE
+#define SET_TRUE_RETURN() v[0].tt=MRB_TT_TRUE
+#define SET_RETURN(n) v[0]=n
+
+#define GET_TT_ARG(n) v[(n)+1].tt
+#define GET_INT_ARG(n) v[(n)+1].value.i
+#define GET_ARY_ARG(n) v[(n)+1]
+#define GET_ARG(n) v[(n)+1]
+#define GET_FLOAT_ARG(n) v[(n)+1].value.d
+#define GET_STRING_ARG(n) v[(n)+1].value.str
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/vm.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/vm.c Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,1362 @@
+/*! @file
+ @brief
+ mruby bytecode executor.
+
+ <pre>
+ Copyright (C) 2015 Kyushu Institute of Technology.
+ Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+
+ Fetch mruby VM bytecodes, decode and execute.
+
+ </pre>
+*/
+
+#include <stdint.h>
+#include <stddef.h>
+#include "vm.h"
+#include "alloc.h"
+#include "static.h"
+#include "vm_config.h"
+#include "opcode.h"
+#include "class.h"
+#include "symbol.h"
+#include "console.h"
+
+#include "c_string.h"
+#include "c_range.h"
+
+
+//================================================================
+/*!@brief
+ find sym[n] from symbol table in irep
+
+ @param p
+ @param n
+ @return symbol string
+*/
+static char *find_irep_symbol( uint8_t *p, int n )
+{
+ int cnt = bin_to_uint32(p);
+ if( n >= cnt ) return 0;
+ p += 4;
+ while( n > 0 ) {
+ uint16_t s = bin_to_uint16(p);
+ p += 2+s+1; // size(2 bytes) + symbol len + '\0'
+ n--;
+ }
+ return (char *)p+2; // skip size(2 bytes)
+}
+
+
+//================================================================
+/*!@brief
+
+*/
+static void not_supported(void)
+{
+ console_printf("Not supported!\n");
+}
+
+
+//================================================================
+/*!@brief
+ Execute NOP
+
+ No operation
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_nop( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute MOVE
+
+ R(A) := R(B)
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_move( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ regs[GETARG_A(code)] = regs[GETARG_B(code)];
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute LOADL
+
+ R(A) := Pool(Bx)
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_loadl( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ int rb = GETARG_Bx(code);
+ mrb_object *ptr = vm->pc_irep->ptr_to_pool;
+ while( rb > 0 ){
+ ptr = ptr->next;
+ rb--;
+ }
+ regs[GETARG_A(code)] = *ptr;
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute LOADI
+
+ R(A) := sBx
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_loadi( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ regs[GETARG_A(code)].value.i = GETARG_sBx(code);
+ regs[GETARG_A(code)].tt = MRB_TT_FIXNUM;
+
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute LOADSYM
+
+ R(A) := Syms(Bx)
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_loadsym( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ int ra = GETARG_A(code);
+ int rb = GETARG_Bx(code);
+ char *sym = find_irep_symbol(vm->pc_irep->ptr_to_sym, rb);
+
+ mrb_sym sym_id = add_sym(sym);
+
+ regs[ra].value.i = sym_id;
+ regs[ra].tt = MRB_TT_SYMBOL;
+
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute LOADNIL
+
+ R(A) := nil
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_loadnil( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ regs[GETARG_A(code)].tt = MRB_TT_NIL;
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute LOADSELF
+
+ R(A) := self
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_loadself( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ regs[GETARG_A(code)] = regs[0];
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute LOADT
+
+ R(A) := true
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_loadt( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ regs[GETARG_A(code)].tt = MRB_TT_TRUE;
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute LOADF
+
+ R(A) := false
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_loadf( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ regs[GETARG_A(code)].tt = MRB_TT_FALSE;
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute GETGLOBAL
+
+ R(A) := getglobal(Syms(Bx))
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_getglobal( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ int ra = GETARG_A(code);
+ int rb = GETARG_Bx(code);
+ char *sym = find_irep_symbol(vm->pc_irep->ptr_to_sym, rb);
+ mrb_sym sym_id = add_sym(sym);
+ regs[ra] = global_object_get(sym_id);
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute SETGLOBAL
+
+ setglobal(Syms(Bx), R(A))
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_setglobal( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ int ra = GETARG_A(code);
+ int rb = GETARG_Bx(code);
+ char *sym = find_irep_symbol(vm->pc_irep->ptr_to_sym, rb);
+ mrb_sym sym_id = add_sym(sym);
+ global_object_add(sym_id, ®s[ra]);
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute GETCONST
+
+ R(A) := constget(Syms(Bx))
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_getconst( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ int ra = GETARG_A(code);
+ int rb = GETARG_Bx(code);
+ char *sym = find_irep_symbol(vm->pc_irep->ptr_to_sym, rb);
+ mrb_sym sym_id = add_sym(sym);
+ regs[ra] = const_get(sym_id);
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute SETCONST
+
+ constset(Syms(Bx),R(A))
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+
+inline static int op_setconst( mrb_vm *vm, uint32_t code, mrb_value *regs ) {
+ int ra = GETARG_A(code);
+ int rb = GETARG_Bx(code);
+ char *sym = find_irep_symbol(vm->pc_irep->ptr_to_sym, rb);
+ mrb_sym sym_id = add_sym(sym);
+ const_add(sym_id, ®s[ra]);
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute JMP
+
+ pc += sBx
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_jmp( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ vm->pc += GETARG_sBx(code) - 1;
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute JMPIF
+
+ if R(A) pc += sBx
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_jmpif( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ if( regs[GETARG_A(code)].tt != MRB_TT_FALSE ) {
+ vm->pc += GETARG_sBx(code) - 1;
+ }
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute JMPNOT
+
+ if not R(A) pc += sBx
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_jmpnot( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ if( regs[GETARG_A(code)].tt == MRB_TT_FALSE ) {
+ vm->pc += GETARG_sBx(code) - 1;
+ }
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute SEND
+
+ R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C))
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_send( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ mrb_value recv = regs[GETARG_A(code)];
+ int rb = GETARG_B(code);
+ char *sym = find_irep_symbol(vm->pc_irep->ptr_to_sym, rb);
+ mrb_sym sym_id = str_to_symid(sym);
+ mrb_proc *m = find_method(vm, recv, sym_id);
+
+ if( m == 0 ) {
+ console_printf("no method(%s)!\n", sym);
+ } else {
+ if( m->c_func == 0 ) {
+ // Ruby method
+ // callinfo
+ mrb_callinfo *callinfo = vm->callinfo + vm->callinfo_top;
+ callinfo->reg_top = vm->reg_top;
+ callinfo->pc_irep = vm->pc_irep;
+ callinfo->pc = vm->pc;
+ callinfo->n_args = GETARG_C(code);
+ vm->callinfo_top++;
+ // target irep
+ vm->pc = 0;
+ vm->pc_irep = m->func.irep;
+ // new regs
+ vm->reg_top += GETARG_A(code);
+ } else {
+ // C func
+ m->func.func(vm, regs+GETARG_A(code));
+ }
+ }
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute ENTER
+
+ arg setup according to flags (23=5:5:1:5:5:1:1)
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_enter( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ mrb_callinfo *callinfo = vm->callinfo + vm->callinfo_top - 1;
+ uint32_t enter_param = GETARG_Ax(code);
+ int def_args = (enter_param >> 13) & 0x1f;
+ int args = (enter_param >> 18) & 0x1f;
+ if( def_args > 0 ){
+ vm->pc += callinfo->n_args - args;
+ }
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute RETURN
+
+ return R(A) (B=normal,in-block return/break)
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_return( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ // return value
+ mrb_value v = regs[GETARG_A(code)];
+ regs[0] = v;
+ // restore irep,pc,regs
+ vm->callinfo_top--;
+ mrb_callinfo *callinfo = vm->callinfo + vm->callinfo_top;
+ vm->reg_top = callinfo->reg_top;
+ vm->pc_irep = callinfo->pc_irep;
+ vm->pc = callinfo->pc;
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute ADD
+
+ R(A) := R(A)+R(A+1) (Syms[B]=:+,C=1)
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_add( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ int rr = GETARG_A(code);
+
+ // support Fixnum + Fixnum
+ if( regs[rr].tt == MRB_TT_FIXNUM && regs[rr+1].tt == MRB_TT_FIXNUM ) {
+ regs[rr].value.i += regs[rr+1].value.i;
+#if MRBC_USE_FLOAT
+ } else if( regs[rr].tt == MRB_TT_FLOAT ){
+ if( regs[rr+1].tt == MRB_TT_FIXNUM ){
+ regs[rr].value.d += regs[rr+1].value.i;
+ } else if( regs[rr+1].tt == MRB_TT_FLOAT ){
+ regs[rr].value.d += regs[rr+1].value.d;
+ } else {
+ op_send(vm, code, regs);
+ }
+#endif
+#if MRBC_USE_STRING
+ } else if( regs[rr].tt == MRB_TT_STRING && regs[rr+1].tt == MRB_TT_STRING ){
+ regs[rr].value.str = mrbc_string_cat(vm, regs[rr].value.str, regs[rr+1].value.str);
+
+#endif
+ } else {
+ op_send(vm, code, regs);
+ }
+
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute ADDI
+
+ R(A) := R(A)+C (Syms[B]=:+)
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_addi( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ int rr = GETARG_A(code);
+
+ // support Fixnum + (value)
+ if( regs[rr].tt == MRB_TT_FIXNUM ) {
+ regs[rr].value.i += GETARG_C(code);
+ } else {
+ not_supported();
+ }
+
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute ADD
+
+ R(A) := R(A)-R(A+1) (Syms[B]=:-,C=1)
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_sub( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ int rr = GETARG_A(code);
+
+ // support Fixnum - Fixnum
+ if( regs[rr].tt == MRB_TT_FIXNUM && regs[rr+1].tt == MRB_TT_FIXNUM ) {
+ regs[rr].value.i -= regs[rr+1].value.i;
+#if MRBC_USE_FLOAT
+ } else if( regs[rr].tt == MRB_TT_FLOAT ){
+ if( regs[rr+1].tt == MRB_TT_FIXNUM ){
+ regs[rr].value.d -= regs[rr+1].value.i;
+ } else if( regs[rr+1].tt == MRB_TT_FLOAT ){
+ regs[rr].value.d -= regs[rr+1].value.d;
+ } else {
+ not_supported();
+ }
+#endif
+ } else {
+ not_supported();
+ }
+
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute
+
+ R(A) := R(A)-C (Syms[B]=:-)
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_subi( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ int rr = GETARG_A(code);
+
+ // support Fixnum + (value)
+ if( regs[rr].tt == MRB_TT_FIXNUM ) {
+ regs[rr].value.i -= GETARG_C(code);
+ } else {
+ not_supported();
+ }
+
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute
+
+ R(A) := R(A)*R(A+1) (Syms[B]=:*)
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_mul( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ int rr = GETARG_A(code);
+
+ // support Fixnum * Fixnum
+ if( regs[rr].tt == MRB_TT_FIXNUM && regs[rr+1].tt == MRB_TT_FIXNUM ) {
+ regs[rr].value.i *= regs[rr+1].value.i;
+#if MRBC_USE_FLOAT
+ } else if( regs[rr].tt == MRB_TT_FLOAT ){
+ if( regs[rr+1].tt == MRB_TT_FIXNUM ){
+ regs[rr].value.d *= regs[rr+1].value.i;
+ } else if( regs[rr+1].tt == MRB_TT_FLOAT ){
+ regs[rr].value.d *= regs[rr+1].value.d;
+ } else {
+ not_supported();
+ }
+#endif
+ } else {
+ not_supported();
+ }
+
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute
+
+ R(A) := R(A)/R(A+1) (Syms[B]=:/)
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_div( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ int rr = GETARG_A(code);
+
+ // support Fixnum * Fixnum
+ if( regs[rr].tt == MRB_TT_FIXNUM && regs[rr+1].tt == MRB_TT_FIXNUM ) {
+ regs[rr].value.i /= regs[rr+1].value.i;
+#if MRBC_USE_FLOAT
+ } else if( regs[rr].tt == MRB_TT_FLOAT ){
+ if( regs[rr+1].tt == MRB_TT_FIXNUM ){
+ regs[rr].value.d /= regs[rr+1].value.i;
+ } else if( regs[rr+1].tt == MRB_TT_FLOAT ){
+ regs[rr].value.d /= regs[rr+1].value.d;
+ } else {
+ not_supported();
+ }
+#endif
+ } else {
+ not_supported();
+ }
+
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute EQ
+
+ R(A) := R(A)==R(A+1) (Syms[B]=:==,C=1)
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_eq( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ int rr = GETARG_A(code);
+ int result;
+
+ //
+ if( mrbc_eq(®s[rr], ®s[rr+1]) ){
+ regs[rr].tt = MRB_TT_TRUE;
+ } else {
+ regs[rr].tt = MRB_TT_FALSE;
+ }
+ return 1;
+
+ // support Fixnum + Fixnum
+ if( regs[rr].tt == MRB_TT_FIXNUM && regs[rr+1].tt == MRB_TT_FIXNUM ) {
+ result = (regs[rr].value.i == regs[rr+1].value.i);
+#if MRBC_USE_FLOAT
+ if( regs[rr].tt == MRB_TT_FLOAT ) {
+ if( regs[rr+1].tt == MRB_TT_FIXNUM ){
+ result = (regs[rr].value.d == regs[rr+1].value.i );
+ } else if( regs[rr+1].tt == MRB_TT_FLOAT ){
+ result = (regs[rr].value.d == regs[rr+1].value.d );
+ } else {
+ result = 0;
+ }
+ }
+#endif
+ } else if( regs[rr].tt == MRB_TT_TRUE ){
+ result = regs[rr+1].tt == MRB_TT_TRUE;
+ } else if( regs[rr].tt == MRB_TT_FALSE ){
+ result = regs[rr+1].tt == MRB_TT_FALSE;
+ } else {
+ op_send(vm,code,regs);
+ result = regs[rr].tt == MRB_TT_TRUE;
+ }
+ if( result ) {
+ regs[rr].tt = MRB_TT_TRUE;
+ } else {
+ regs[rr].tt = MRB_TT_FALSE;
+ }
+
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute LT
+
+ R(A) := R(A)<R(A+1) (Syms[B]=:<,C=1)
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_lt( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ int rr = GETARG_A(code);
+ int result;
+
+ // support Fixnum + Fixnum
+ if( regs[rr].tt == MRB_TT_FIXNUM && regs[rr+1].tt == MRB_TT_FIXNUM ) {
+ result = regs[rr].value.i < regs[rr+1].value.i;
+#if MRBC_USE_FLOAT
+ } else if( regs[rr].tt == MRB_TT_FLOAT ){
+ if( regs[rr+1].tt == MRB_TT_FIXNUM ){
+ result = regs[rr].value.d < regs[rr+1].value.i;
+ } else if( regs[rr+1].tt == MRB_TT_FLOAT ){
+ result = regs[rr].value.d < regs[rr+1].value.d;
+ } else {
+ result = 0;
+ }
+#endif
+ } else {
+ result = 0;
+ not_supported();
+ }
+
+ if( result ) {
+ regs[rr].tt = MRB_TT_TRUE;
+ } else {
+ regs[rr].tt = MRB_TT_FALSE;
+ }
+
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute LE
+
+ R(A) := R(A)<=R(A+1) (Syms[B]=:<=,C=1)
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_le( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ int rr = GETARG_A(code);
+ int result;
+
+ // support Fixnum + Fixnum
+ if( regs[rr].tt == MRB_TT_FIXNUM && regs[rr+1].tt == MRB_TT_FIXNUM ) {
+ result = regs[rr].value.i <= regs[rr+1].value.i;
+#if MRBC_USE_FLOAT
+ } else if( regs[rr].tt == MRB_TT_FLOAT ){
+ if( regs[rr+1].tt == MRB_TT_FIXNUM ){
+ result = regs[rr].value.d <= regs[rr+1].value.i;
+ } else if( regs[rr+1].tt == MRB_TT_FLOAT ){
+ result = regs[rr].value.d <= regs[rr+1].value.d;
+ } else {
+ result = 0;
+ }
+#endif
+ } else {
+ result = 0;
+ not_supported();
+ }
+ if( result ) {
+ regs[rr].tt = MRB_TT_TRUE;
+ } else {
+ regs[rr].tt = MRB_TT_FALSE;
+ }
+
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute GE
+
+ R(A) := R(A)>=R(A+1) (Syms[B]=:>=,C=1)
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_gt( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ int rr = GETARG_A(code);
+ int result;
+
+ // support Fixnum + Fixnum
+ if( regs[rr].tt == MRB_TT_FIXNUM && regs[rr+1].tt == MRB_TT_FIXNUM ) {
+ result = regs[rr].value.i > regs[rr+1].value.i;
+#if MRBC_USE_FLOAT
+ } else if( regs[rr].tt == MRB_TT_FLOAT ){
+ if( regs[rr+1].tt == MRB_TT_FIXNUM ){
+ result = regs[rr].value.d > regs[rr+1].value.i;
+ } else if( regs[rr+1].tt == MRB_TT_FLOAT ){
+ result = regs[rr].value.d > regs[rr+1].value.d;
+ } else {
+ result = 0;
+ }
+#endif
+ } else {
+ result = 0;
+ not_supported();
+ }
+ if( result ) {
+ regs[rr].tt = MRB_TT_TRUE;
+ } else {
+ regs[rr].tt = MRB_TT_FALSE;
+ }
+
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute GE
+
+ R(A) := R(A)>=R(A+1) (Syms[B]=:>=,C=1)
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_ge( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ int rr = GETARG_A(code);
+ int result;
+
+ // support Fixnum + Fixnum
+ if( regs[rr].tt == MRB_TT_FIXNUM && regs[rr+1].tt == MRB_TT_FIXNUM ) {
+ result = regs[rr].value.i >= regs[rr+1].value.i;
+#if MRBC_USE_FLOAT
+ } else if( regs[rr].tt == MRB_TT_FLOAT ){
+ if( regs[rr+1].tt == MRB_TT_FIXNUM ){
+ result = regs[rr].value.d >= regs[rr+1].value.i;
+ } else if( regs[rr+1].tt == MRB_TT_FLOAT ){
+ result = regs[rr].value.d >= regs[rr+1].value.d;
+ } else {
+ result = 0;
+ }
+#endif
+ } else {
+ result = 0;
+ not_supported();
+ }
+ if( result ) {
+ regs[rr].tt = MRB_TT_TRUE;
+ } else {
+ regs[rr].tt = MRB_TT_FALSE;
+ }
+
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Make Array
+
+ R(A) := ary_new(R(B),R(B+1)..R(B+C))
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_array( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ int arg_a = GETARG_A(code);
+ int arg_b = GETARG_B(code);
+ int arg_c = GETARG_C(code);
+ mrb_value *ptr;
+
+ mrb_value v;
+ v.tt = MRB_TT_ARRAY;
+ v.value.obj = 0;
+
+ if( arg_c >= 0 ){
+ mrb_object *p;
+ // ptr[0] : array info
+ // ptr[1..] : array elements
+ ptr = (mrb_value*)mrbc_alloc(vm, sizeof(mrb_value)*(arg_c + 1));
+ if( ptr == NULL ) return 0; // ENOMEM
+
+ v.value.obj = ptr;
+ ptr->tt = MRB_TT_FIXNUM;
+ ptr->value.i = arg_c;
+
+ p = ptr + 1;
+ while( arg_c > 0 ){
+ p->tt = regs[arg_b].tt;
+ p->value = regs[arg_b].value;
+ p++;
+ arg_c--;
+ arg_b++;
+ }
+ }
+
+ regs[arg_a] = v;
+
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Create string object
+
+ R(A) := str_dup(Lit(Bx))
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_string( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ mrb_value v;
+ v.tt = MRB_TT_STRING;
+
+ int arg_b = GETARG_Bx(code);
+ mrb_object *ptr = vm->pc_irep->ptr_to_pool;
+ while( arg_b > 0 ){
+ ptr = ptr->next;
+ arg_b--;
+ }
+ v.value.str = mrbc_string_dup(vm, ptr->value.str);
+
+ int arg_a = GETARG_A(code);
+ regs[arg_a] = v;
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Create HASH object
+
+ R(A) := hash_new(R(B),R(B+1)..R(B+C))
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_hash( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ int arg_a = GETARG_A(code);
+ int arg_b = GETARG_B(code);
+ int arg_c = GETARG_C(code);
+
+ mrb_value v; // return value
+ v.tt = MRB_TT_HASH;
+
+ // make handle for hash pair
+ mrb_value *handle = (mrb_value *)mrbc_alloc(vm, sizeof(mrb_value));
+ if( handle == NULL ) return 0; // ENOMEM
+
+ v.value.obj = handle;
+ handle->tt = MRB_TT_HANDLE;
+
+ // make hash
+ mrb_value *hash = (mrb_value *)mrbc_alloc(vm, sizeof(mrb_value)*(arg_c*2+1));
+ if( hash == NULL ) return 0; // ENOMEM
+ handle->value.obj = hash;
+
+ hash[0].tt = MRB_TT_FIXNUM;
+ hash[0].value.i = arg_c;
+
+ mrb_value *src = ®s[arg_b];
+ mrb_value *dst = &hash[1];
+ while( arg_c > 0 ){
+ // copy key
+ *dst++ = *src++;
+
+ // copy value
+ *dst++ = *src++;
+
+ arg_c--;
+ }
+
+ regs[arg_a] = v;
+
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute LAMBDA
+
+ R(A) := lambda(SEQ[Bz],Cz)
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_lambda( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ // int c = GETARG_C(code); // TODO: Add flags support for OP_LAMBDA
+ int b = GETARG_b(code); // sequence position in irep list
+ mrb_proc *proc = mrbc_rproc_alloc(vm, "(lambda)");
+ mrb_irep *current = vm->irep;
+ mrb_irep *p = current->next; //starting from next for current sequence;
+ // code length is p->ilen * sizeof(uint32_t);
+ int i;
+ for (i=0; i < b; i++) {
+ p = p->next;
+ }
+ proc->c_func = 0;
+ proc->func.irep = p;
+ int a = GETARG_A(code);
+ regs[a].tt = MRB_TT_PROC;
+ regs[a].value.proc = proc;
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute RANGE
+
+ R(A) := R(A) := range_new(R(B),R(B+1),C)
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_range( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ int a = GETARG_A(code);
+ int b = GETARG_B(code);
+ int c = GETARG_C(code);
+ regs[a] = mrbc_range_new(vm, ®s[b], ®s[b+1], c);
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute CLASS
+
+ R(A) := newclass(R(A),Syms(B),R(A+1))
+ Syms(B): class name
+ R(A+1): super class
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_class( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+
+
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute METHOD
+
+ R(A).newmethod(Syms(B),R(A+1))
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_method( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ int a = GETARG_A(code);
+ mrb_proc *rproc = regs[a+1].value.proc;
+
+ if( regs[a].tt == MRB_TT_CLASS ) {
+ mrb_class *cls = regs[a].value.cls;
+ int b = GETARG_B(code);
+ // sym_id : method name
+ mrb_irep *cur_irep = vm->pc_irep;
+ char *sym = find_irep_symbol(cur_irep->ptr_to_sym, b);
+ int sym_id = add_sym( sym );
+ mrbc_define_method_proc(vm, cls, sym_id, rproc);
+ }
+
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute TCLASS
+
+ R(A) := target_class
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_tclass( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ regs[GETARG_A(code)].tt = MRB_TT_CLASS;
+ regs[GETARG_A(code)].value.cls = vm->target_class;
+
+ return 0;
+}
+
+
+//================================================================
+/*!@brief
+ Execute STOP
+
+ stop VM
+
+ @param vm A pointer of VM.
+ @param code bytecode
+ @param regs vm->regs + vm->reg_top
+ @retval 0 No error.
+*/
+inline static int op_stop( mrb_vm *vm, uint32_t code, mrb_value *regs )
+{
+ vm->flag_preemption = 1;
+ return -1;
+}
+
+
+//================================================================
+/*!@brief
+ Allocate new IREP
+
+ @param vm Pointer of VM.
+ @return Pointer of new IREP.
+*/
+mrb_irep *new_irep(mrb_vm *vm)
+{
+ mrb_irep *p = (mrb_irep *)mrbc_alloc(vm, sizeof(mrb_irep));
+ return p;
+}
+
+
+//================================================================
+/*!@brief
+ VM initializer.
+
+ Get a VM from static heap.
+
+ @return Pointer of struct VM in static area.
+
+ @code
+ init_static();
+ struct VM *vm = vm_open();
+ @endcode
+*/
+struct VM *vm_open(void)
+{
+ int i;
+ mrb_vm *p = 0;
+ for( i=0 ; i<MAX_VM_COUNT ; i++ ){
+ if( mrbc_vm[i].priority < 0 ){
+ p = mrbc_vm + i;
+ break;
+ }
+ }
+
+ if( p != 0 ){
+ p->priority = 1;
+ p->pc = 0;
+ p->callinfo_top = 0;
+ }
+
+ return p;
+}
+
+
+//================================================================
+/*!@brief
+ VM finalizer.
+
+ @param vm Pointer of VM
+*/
+void vm_close(struct VM *vm)
+{
+ vm->priority = -1;
+ mrbc_free_all(vm);
+
+}
+
+
+//================================================================
+/*!@brief
+ Boot the VM.
+
+ @param vm Pointer of VM
+*/
+// init vm
+void vm_boot(struct VM *vm)
+{
+ vm->pc_irep = vm->irep;
+ vm->pc = 0;
+ vm->reg_top = 0;
+ // set self to reg[0]
+ vm->top_self = mrbc_obj_alloc(vm, MRB_TT_OBJECT);
+ vm->top_self->value.cls = mrbc_class_object;
+ vm->regs[0].tt = MRB_TT_OBJECT;
+ vm->regs[0].value.obj = vm->top_self;
+ // target_class
+ vm->target_class = vm->top_self->value.cls;
+ vm->error_code = 0;
+ vm->flag_preemption = 0;
+}
+
+
+//================================================================
+/*!@brief
+ Fetch a bytecode and execute
+
+ @param vm A pointer of VM.
+ @retval 0 No error.
+*/
+int vm_run( mrb_vm *vm )
+{
+ int ret = 0;
+
+ do {
+ // get one bytecode
+ uint32_t code = bin_to_uint32(vm->pc_irep->code + vm->pc * 4);
+ vm->pc++;
+
+ // regs
+ mrb_value *regs = vm->regs + vm->reg_top;
+
+ // Dispatch
+ enum OPCODE opcode = GET_OPCODE(code);
+ switch( opcode ) {
+ case OP_NOP: ret = op_nop (vm, code, regs); break;
+ case OP_MOVE: ret = op_move (vm, code, regs); break;
+ case OP_LOADL: ret = op_loadl (vm, code, regs); break;
+ case OP_LOADI: ret = op_loadi (vm, code, regs); break;
+ case OP_LOADSYM: ret = op_loadsym (vm, code, regs); break;
+ case OP_LOADNIL: ret = op_loadnil (vm, code, regs); break;
+ case OP_LOADSELF: ret = op_loadself (vm, code, regs); break;
+ case OP_LOADT: ret = op_loadt (vm, code, regs); break;
+ case OP_LOADF: ret = op_loadf (vm, code, regs); break;
+ case OP_GETGLOBAL: ret = op_getglobal (vm, code, regs); break;
+ case OP_SETGLOBAL: ret = op_setglobal (vm, code, regs); break;
+ case OP_GETCONST: ret = op_getconst (vm, code, regs); break;
+ case OP_SETCONST: ret = op_setconst (vm, code, regs); break;
+ case OP_JMP: ret = op_jmp (vm, code, regs); break;
+ case OP_JMPIF: ret = op_jmpif (vm, code, regs); break;
+ case OP_JMPNOT: ret = op_jmpnot (vm, code, regs); break;
+ case OP_SEND: ret = op_send (vm, code, regs); break;
+ case OP_ENTER: ret = op_enter (vm, code, regs); break;
+ case OP_RETURN: ret = op_return (vm, code, regs); break;
+ case OP_ADD: ret = op_add (vm, code, regs); break;
+ case OP_ADDI: ret = op_addi (vm, code, regs); break;
+ case OP_SUB: ret = op_sub (vm, code, regs); break;
+ case OP_SUBI: ret = op_subi (vm, code, regs); break;
+ case OP_MUL: ret = op_mul (vm, code, regs); break;
+ case OP_DIV: ret = op_div (vm, code, regs); break;
+ case OP_EQ: ret = op_eq (vm, code, regs); break;
+ case OP_LT: ret = op_lt (vm, code, regs); break;
+ case OP_LE: ret = op_le (vm, code, regs); break;
+ case OP_GT: ret = op_gt (vm, code, regs); break;
+ case OP_GE: ret = op_ge (vm, code, regs); break;
+ case OP_ARRAY: ret = op_array (vm, code, regs); break;
+ case OP_STRING: ret = op_string (vm, code, regs); break;
+ case OP_HASH: ret = op_hash (vm, code, regs); break;
+ case OP_LAMBDA: ret = op_lambda (vm, code, regs); break;
+ case OP_RANGE: ret = op_range (vm, code, regs); break;
+ case OP_CLASS: ret = op_class (vm, code, regs); break;
+ case OP_METHOD: ret = op_method (vm, code, regs); break;
+ case OP_TCLASS: ret = op_tclass (vm, code, regs); break;
+ case OP_STOP: ret = op_stop (vm, code, regs); break;
+ default:
+ console_printf("Skip OP=%02x\n", GET_OPCODE(code));
+ break;
+ }
+ } while( !vm->flag_preemption );
+
+ return ret;
+}
+
+
+#ifdef MRBC_DEBUG
+
+//================================================================
+/*!@brief
+
+ @param vm Pointer of VM.
+ @param irep
+ @return
+*/
+void debug_irep(mrb_vm *vm, mrb_irep *irep)
+{
+ if( irep->unused == 1 ) {
+ console_printf(" not used.\n");
+ return;
+ }
+ console_printf(" code:0x%x\n", (int)((char *)irep->code - (char *)vm->mrb));
+ console_printf(" regs:%d\n", irep->nregs);
+ console_printf(" locals:%d\n", irep->nlocals);
+}
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/vm.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mrubyc/vm.h Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,140 @@
+/*! @file
+ @brief
+ mruby bytecode executor.
+
+ <pre>
+ Copyright (C) 2015 Kyushu Institute of Technology.
+ Copyright (C) 2015 Shimane IT Open-Innovation Center.
+
+ This file is distributed under BSD 3-Clause License.
+
+ Fetch mruby VM bytecodes, decode and execute.
+
+ </pre>
+*/
+
+#ifndef MRBC_SRC_VM_H_
+#define MRBC_SRC_VM_H_
+
+#include <stdint.h>
+#include "value.h"
+#include "vm_config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+//================================================================
+/*!@brief
+
+*/
+typedef struct IREP {
+ int16_t unused; //! unused flag
+ struct IREP *next; //! irep linked list
+
+ uint8_t *code;
+ mrb_object *ptr_to_pool;
+ uint8_t *ptr_to_sym;
+
+ int16_t nlocals;
+ int16_t nregs;
+ int16_t rlen;
+ int32_t ilen;
+
+ int16_t iseq;
+
+} mrb_irep;
+
+
+//================================================================
+/*!@brief
+
+*/
+typedef struct CALLINFO {
+ mrb_irep *pc_irep;
+ uint32_t pc;
+ uint32_t reg_top;
+ uint8_t n_args; // num of args
+} mrb_callinfo;
+
+
+//================================================================
+/*!@brief
+
+*/
+typedef struct VM {
+ mrb_irep *irep; // irep linked list
+
+ uint8_t vm_id; // vm_id : 1..n
+ int16_t priority; //
+ const uint8_t *mrb; // bytecode
+
+ mrb_irep *pc_irep; // PC
+ int16_t pc; // PC
+
+ int reg_top;
+ mrb_value regs[MAX_REGS_SIZE];
+ int callinfo_top;
+ mrb_callinfo callinfo[MAX_CALLINFO_SIZE];
+
+ mrb_class *target_class;
+ mrb_object *top_self; // ?
+
+ int32_t error_code;
+
+ volatile int8_t flag_preemption;
+} mrb_vm;
+
+
+
+mrb_irep *new_irep(mrb_vm *vm);
+struct VM *vm_open(void);
+void vm_close(struct VM *vm);
+void vm_boot(struct VM *vm);
+int vm_run(struct VM *vm);
+
+
+//================================================================
+/*!@brief
+ Get 32bit value from memory big endian.
+
+ @param s Pointer of memory.
+ @return 32bit unsigned value.
+*/
+inline static uint32_t bin_to_uint32( const void *s )
+{
+ uint8_t *s1 = (uint8_t *)s;
+ uint32_t ret;
+
+ ret = *s1++;
+ ret = (ret << 8) + *s1++;
+ ret = (ret << 8) + *s1++;
+ ret = (ret << 8) + *s1;
+ return ret;
+}
+
+
+//================================================================
+/*!@brief
+ Get 16bit value from memory big endian.
+
+ @param s Pointer of memory.
+ @return 16bit unsigned value.
+*/
+inline static uint16_t bin_to_uint16( const void *s )
+{
+ uint8_t *s1 = (uint8_t *)s;
+ uint16_t ret;
+
+ ret = *s1++;
+ ret = (ret << 8) + *s1;
+ return ret;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff -r 000000000000 -r 33feccbba3ff mrubyc/vm_config.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mrubyc/vm_config.h Wed Feb 15 01:03:35 2017 +0000 @@ -0,0 +1,76 @@ +/*! @file + @brief + Global configration of mruby/c VM's + + <pre> + Copyright (C) 2015 Kyushu Institute of Technology. + Copyright (C) 2015 Shimane IT Open-Innovation Center. + + This file is distributed under BSD 3-Clause License. + + + </pre> +*/ + +#ifndef MRBC_SRC_VM_CONFIG_H_ +#define MRBC_SRC_VM_CONFIG_H_ + +/* maximum number of VMs */ +#ifndef MAX_VM_COUNT +#define MAX_VM_COUNT 5 +#endif + +/* maximum size of registers */ +#ifndef MAX_REGS_SIZE +#define MAX_REGS_SIZE 100 +#endif + +/* maximum size of callinfo (callstack) */ +#ifndef MAX_CALLINFO_SIZE +#define MAX_CALLINFO_SIZE 100 +#endif + +/* maximum number of objects */ +#ifndef MAX_OBJECT_COUNT +#define MAX_OBJECT_COUNT 400 +#endif + +/* maximum number of classes */ +#ifndef MAX_CLASS_COUNT +#define MAX_CLASS_COUNT 20 +#endif + +/* maximum size of symbol table */ +#ifndef MAX_SYMBOLS_SIZE +#define MAX_SYMBOLS_SIZE 400 +#endif + +/* maximum number of symbols */ +#ifndef MAX_SYMBOLS_COUNT +#define MAX_SYMBOLS_COUNT 200 +#endif + +/* maximum size of global objects */ +#ifndef MAX_GLOBAL_OBJECT_SIZE +#define MAX_GLOBAL_OBJECT_SIZE 20 +#endif + +/* maximum size of consts */ +#ifndef MAX_CONST_COUNT +#define MAX_CONST_COUNT 20 +#endif + + +/* Configure environment */ +/* 0: NOT USE */ +/* 1: USE */ + +/* USE Float. Support Float class */ +//#define MRBC_USE_FLOAT 1 + +/* USE String. Support String class */ +#define MRBC_USE_STRING 1 + + +#endif +
diff -r 000000000000 -r 33feccbba3ff sample1.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sample1.c Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,27 @@
+/* dumped in big endian order.
+ use `mrbc -e` option for better performance on little endian CPU. */
+#include <stdint.h>
+const uint8_t
+#if defined __GNUC__
+__attribute__((aligned(4)))
+#elif defined _MSC_VER
+__declspec(align(4))
+#endif
+sample1[] = {
+0x52,0x49,0x54,0x45,0x30,0x30,0x30,0x33,0x5e,0x0d,0x00,0x00,0x00,0xe9,0x4d,0x41,
+0x54,0x5a,0x30,0x30,0x30,0x30,0x49,0x52,0x45,0x50,0x00,0x00,0x00,0xb6,0x30,0x30,
+0x30,0x30,0x00,0x00,0x00,0xae,0x00,0x02,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x1b,
+0x00,0xbf,0xff,0x83,0x00,0x40,0x0a,0x97,0x01,0x00,0x40,0x01,0x01,0xbf,0xff,0x83,
+0x01,0x00,0x00,0xb2,0x01,0x40,0x01,0x19,0x00,0xc0,0x00,0x03,0x00,0x40,0x00,0x97,
+0x00,0xbf,0xff,0x83,0x01,0x00,0x00,0x89,0x01,0xbf,0xff,0x83,0x01,0x00,0x00,0xb2,
+0x01,0x40,0x00,0x99,0x00,0xc0,0x00,0x03,0x01,0x00,0x00,0x06,0x01,0x80,0x40,0x01,
+0x01,0x00,0x80,0xa0,0x01,0x00,0x00,0x06,0x01,0x80,0x40,0x01,0x01,0x00,0xc0,0xa0,
+0x01,0x00,0x00,0x06,0x01,0xc0,0x31,0x83,0x01,0x01,0x00,0xa0,0x01,0x00,0x00,0x07,
+0x01,0x3f,0xf4,0x98,0x01,0x00,0x00,0x05,0x00,0x00,0x00,0x4a,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x05,0x00,0x02,0x3d,0x3d,0x00,0x00,0x04,0x24,0x73,0x77,0x31,0x00,
+0x00,0x0a,0x6c,0x65,0x64,0x31,0x5f,0x77,0x72,0x69,0x74,0x65,0x00,0x00,0x04,0x70,
+0x75,0x74,0x73,0x00,0x00,0x05,0x64,0x65,0x6c,0x61,0x79,0x00,0x4c,0x56,0x41,0x52,
+0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x01,0x00,0x03,0x6c,0x65,0x64,0x00,0x00,0x00,
+0x01,0x45,0x4e,0x44,0x00,0x00,0x00,0x00,0x08,
+};
+
diff -r 000000000000 -r 33feccbba3ff sample1.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sample1.rb Wed Feb 15 01:03:35 2017 +0000 @@ -0,0 +1,15 @@ +led = 0 +while(true) + if(led == 0) + led = 1 + else + led = 0 + end + if($sw1 == 0) + led = 1 + end + led1_write( led ) + puts led + delay 100 +end +
diff -r 000000000000 -r 33feccbba3ff sample2.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sample2.c Wed Feb 15 01:03:35 2017 +0000
@@ -0,0 +1,20 @@
+/* dumped in big endian order.
+ use `mrbc -e` option for better performance on little endian CPU. */
+#include <stdint.h>
+const uint8_t
+#if defined __GNUC__
+__attribute__((aligned(4)))
+#elif defined _MSC_VER
+__declspec(align(4))
+#endif
+sample2[] = {
+0x52,0x49,0x54,0x45,0x30,0x30,0x30,0x33,0xe4,0x90,0x00,0x00,0x00,0x72,0x4d,0x41,
+0x54,0x5a,0x30,0x30,0x30,0x30,0x49,0x52,0x45,0x50,0x00,0x00,0x00,0x54,0x30,0x30,
+0x30,0x30,0x00,0x00,0x00,0x4c,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x08,
+0x00,0x40,0x01,0x97,0x00,0x80,0x00,0x06,0x00,0x80,0x00,0x20,0x00,0x80,0x00,0x8a,
+0x00,0x80,0x00,0x07,0x00,0xbf,0xfd,0x98,0x00,0x80,0x00,0x05,0x00,0x00,0x00,0x4a,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x08,0x73,0x77,0x31,0x5f,0x72,0x65,
+0x61,0x64,0x00,0x00,0x04,0x24,0x73,0x77,0x31,0x00,0x45,0x4e,0x44,0x00,0x00,0x00,
+0x00,0x08,
+};
+
diff -r 000000000000 -r 33feccbba3ff sample2.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sample2.rb Wed Feb 15 01:03:35 2017 +0000 @@ -0,0 +1,4 @@ +while(true) + $sw1 = sw1_read() +end +