This is a port of the mruby/c tutorial Chapter 03 to the mbed environment.
For details, refer to the following.
http://www.s-itoc.jp/activity/research/mrubyc/mrubyc_tutorial/436
Note:There is a change in rtt0.h from the original source in the mruby/c. It was necessary for inclusion in C ++ source.
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 +