Skip to content

Commit

Permalink
support hash type
Browse files Browse the repository at this point in the history
  • Loading branch information
goccy committed Aug 10, 2013
1 parent 45a6d40 commit a17377b
Show file tree
Hide file tree
Showing 7 changed files with 614 additions and 61 deletions.
2 changes: 2 additions & 0 deletions example/condition.pl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
$a = $a + 1;
say $a;
say $a == 2;
if ($a != 2) {
say "true";
} elsif ($a == 2) {
Expand All @@ -34,3 +35,4 @@
say 0 && 2; # 0
say 1 || 2; # 1
say 0 || 2; # 2
34 changes: 34 additions & 0 deletions example/hash.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use strict;
use warnings;
use Compiler::Lexer;
use Compiler::Parser;
use Compiler::Parser::AST::Renderer;
use Compiler::CodeGenerator::LLVM;

my $code = do { local $/; <DATA> };
my $tokens = Compiler::Lexer->new('')->tokenize($code);
my $parser = Compiler::Parser->new();
my $ast = $parser->parse($tokens);
Compiler::Parser::AST::Renderer->new->render($ast);
my $generator = Compiler::CodeGenerator::LLVM->new();
my $llvm_ir = $generator->generate($ast);
open my $fh, '>', 'hash.ll';
print $fh $llvm_ir;
close $fh;
$generator = Compiler::CodeGenerator::LLVM->new();
$generator->debug_run($ast);

__DATA__
my %a = (a => 1, b => 2);
say %a;
=hoge
say $a{a};
say $a{b};
$a{a} = 3;
say %a;
my @b = %a;
say @b;
=cut
88 changes: 87 additions & 1 deletion gen/runtime_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ UnionType u;
void print_object(UnionType _o)
{
void *o = _o.o;
//fprintf(stderr, "type = [%d]\n", TYPE(o));
switch (TYPE(o)) {
case Int:
fprintf(stdout, "%d", to_Int(o));
Expand All @@ -12,14 +13,17 @@ void print_object(UnionType _o)
fprintf(stdout, "%f", _o.d);
break;
case String:
fprintf(stdout, "%s", to_String(o));
fprintf(stdout, "%s", (to_String(o))->s);
break;
case Array:
print(to_Array(o));
break;
case ArrayRef:
fprintf(stdout, "ARRAY(%p)", o);
break;
case Hash:
print_hash(to_Hash(o));
break;
case ObjectType: {
Object *object = to_Object(o);
print_object(object->v);
Expand All @@ -30,6 +34,17 @@ void print_object(UnionType _o)
}
}

void print_hash(HashObject *hash)
{
size_t key_n = hash->size;
size_t i = 0;
for (i = 0; i < key_n; i++) {
StringObject *key = hash->keys[i];
fprintf(stdout, "%s", key->s);
print_object(hash->table[key->hash]);
}
}

void print(ArrayObject *array)
{
size_t size = array->size;
Expand Down Expand Up @@ -112,6 +127,77 @@ Object *map(ArrayObject *args)
}
*/

UnionType undef;
void new_Undef(void)
{
UndefObject *o = (UndefObject *)calloc(sizeof(UndefObject), 1);
undef.o = UNDEF_init(o);
}

UnionType *base_hash_table;
void init_table(void)
{
UnionType *table = (UnionType *)calloc(sizeof(UnionType), HASH_TABLE_SIZE);
size_t i;
for (i = 0; i < HASH_TABLE_SIZE; i++) {
table[i] = undef;
}
base_hash_table = table;
}

void global_init(void)
{
new_Undef();
init_table();
}

/**
* An implementation of the djb2 hash function by Dan Bernstein.
*/
unsigned long make_hash(char* _str, size_t len)
{
char* str = _str;
unsigned long hash = 5381;
while (len--) {
/* hash * 33 + c */
hash = ((hash << 5) + hash) + *str++;
}
return hash;
}

UnionType new_String(char *str)
{
UnionType ret;
StringObject *o = (StringObject *)calloc(sizeof(StringObject), 1);
o->header = String;
o->s = str;
o->len = strlen(str);
o->hash = make_hash(str, o->len) % HASH_TABLE_SIZE;
ret.o = STRING_init(o);
return ret;
}

UnionType new_Hash(ArrayObject *array)
{
UnionType ret;
HashObject *hash = (HashObject *)calloc(sizeof(HashObject), 1);
hash->table = (UnionType *)calloc(sizeof(UnionType), HASH_TABLE_SIZE);
memcpy(hash->table, base_hash_table, sizeof(UnionType) * HASH_TABLE_SIZE);
hash->keys = (StringObject **)calloc(sizeof(void *), HASH_TABLE_SIZE);
size_t size = array->size;
int key_n = 0;
size_t i = 0;
UnionType *list = array->list;
for (i = 0; i < size; i += 2, key_n++) {
StringObject *key = to_String(list[i].o);
hash->table[key->hash] = list[i + 1];
hash->keys[key_n] = key;
}
hash->size = key_n;
ret.o = HASH_init(hash);
return ret;
}

Object *new_Object(void)
{
return (Object *)malloc(sizeof(Object));
Expand Down
57 changes: 41 additions & 16 deletions gen/runtime_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ typedef enum {
HashRef,
ObjectType,
BlessedObject,
Unknown
Undefined
} Type;

typedef union {
Expand All @@ -32,28 +32,49 @@ typedef struct _Object {
Value v;
} Object;

typedef struct _ArrayRef {
int type;
Value v;
} ArrayRefObject;
typedef struct _Undef {
int header;
} UndefObject;

typedef struct _String {
int header;
char *s;
size_t len;
unsigned long hash;
} StringObject;

typedef struct _Array {
int type;
Value *list;
size_t size;
} ArrayObject;

#define NaN (0xFFF0000000000000)
#define MASK (0x00000000FFFFFFFF)
#define _TYPE (0x000F000000000000)
#define INT_TAG (uint64_t)(0x0001000000000000)
#define STRING_TAG (uint64_t)(0x0002000000000000)
#define ARRAY_TAG (uint64_t)(0x0003000000000000)
#define ARRAY_REF_TAG (uint64_t)(0x0004000000000000)
#define HASH_TAG (uint64_t)(0x0005000000000000)
#define HASH_REF_TAG (uint64_t)(0x0006000000000000)
#define OBJECT_TAG (uint64_t)(0x0007000000000000)
typedef struct _ArrayRef {
int type;
Value v;
} ArrayRefObject;

typedef struct _Hash {
int header;
Value *table;
StringObject **keys;
size_t size;
} HashObject;

#define NaN (0xFFF0000000000000)
#define MASK (0x00000000FFFFFFFF)
#define _TYPE (0x000F000000000000)
#define INT_TAG (uint64_t)(0x0001000000000000)
#define STRING_TAG (uint64_t)(0x0002000000000000)
#define ARRAY_TAG (uint64_t)(0x0003000000000000)
#define ARRAY_REF_TAG (uint64_t)(0x0004000000000000)
#define HASH_TAG (uint64_t)(0x0005000000000000)
#define HASH_REF_TAG (uint64_t)(0x0006000000000000)
#define OBJECT_TAG (uint64_t)(0x0007000000000000)
#define BLESSED_OBJECT_TAG (uint64_t)(0x0008000000000000)
#define UNDEF_TAG (uint64_t)(0x0009000000000000)

#define HASH_TABLE_SIZE 512

#define TYPE(data) ((((uint64_t)data & NaN) == NaN) * (((uint64_t)data & _TYPE) >> 48))

Expand All @@ -63,19 +84,23 @@ typedef struct _Array {
#define ARRAY_init(data) (void *)((uint64_t)data | NaN | ARRAY_TAG)
#define HASH_init(data) (void *)((uint64_t)data | NaN | HASH_TAG)
#define OBJECT_init(data) (void *)((uint64_t)data | NaN | OBJECT_TAG)
#define UNDEF_init(data) (void *)((uint64_t)data | NaN | UNDEF_TAG)

#define to_Int(o) ((intptr_t)o)
#define to_Double(o) (*(double *)o)
#define to_String(o) (char *)((uint64_t)o ^ (NaN | STRING_TAG))
#define to_String(o) (StringObject *)((uint64_t)o ^ (NaN | STRING_TAG))
#define to_Object(o) (Object *)((uint64_t)o ^ (NaN | OBJECT_TAG))
#define to_Array(o) (ArrayObject *)((uint64_t)o ^ (NaN | ARRAY_TAG))
#define to_Hash(o) (HashObject *)((uint64_t)o ^ (NaN | HASH_TAG))

#define TYPE_CHECK(o, T) do { \
if (TYPE(o) != T) { \
assert(0 && "Type Error!\n"); \
} \
} while (0)

void print(ArrayObject *array);
void print_hash(HashObject *hash);

#define SET(ret, a, b, op) do { \
switch (TYPE(b->o)) { \
Expand Down
Loading

0 comments on commit a17377b

Please sign in to comment.