Started work on blocks and the hash table.
This commit is contained in:
parent
efac7f7747
commit
70393ef9ae
3
examples/function.scl
Normal file
3
examples/function.scl
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
f(n) = 2 * n
|
||||||
|
|
||||||
|
f(5)
|
31
src/ast.c
31
src/ast.c
@ -9,7 +9,8 @@ extern AST* root;
|
|||||||
static char* asttype_names[] = {
|
static char* asttype_names[] = {
|
||||||
[AST_TYPE_CALL] = "FUNC CALL",
|
[AST_TYPE_CALL] = "FUNC CALL",
|
||||||
[AST_TYPE_NUM] = "NUMBER",
|
[AST_TYPE_NUM] = "NUMBER",
|
||||||
[AST_TYPE_VREF] = "VAR REFERENCE"
|
[AST_TYPE_VREF] = "VAR REFERENCE",
|
||||||
|
[AST_TYPE_BLOCK] = "BLOCK",
|
||||||
};
|
};
|
||||||
|
|
||||||
AST* ast_init(ASTType type, void* data) {
|
AST* ast_init(ASTType type, void* data) {
|
||||||
@ -125,3 +126,31 @@ void ast_vref_print(ASTVrefData* data, int i) {
|
|||||||
|
|
||||||
INDENT_END;
|
INDENT_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASTBlockData* ast_block_data_init(AST** inside, size_t ln) {
|
||||||
|
ASTBlockData* block = malloc(sizeof(ASTBlockData));
|
||||||
|
|
||||||
|
block->inside = calloc(ln, sizeof(AST));
|
||||||
|
block->ln = ln;
|
||||||
|
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ast_block_data_destroy(ASTBlockData* block) {
|
||||||
|
for (size_t i = 0; i < block->ln; i++) {
|
||||||
|
ast_destroy(block->inside[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(block->inside);
|
||||||
|
free(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ast_block_data_print(ASTBlockData* data, int depth) {
|
||||||
|
INDENT_BEGIN(depth);
|
||||||
|
|
||||||
|
INDENT_TITLE("BLOCK", data);
|
||||||
|
INDENT_FIELD("ln", "%ld", data->ln);
|
||||||
|
INDENT_FIELD_LIST("inside", data->inside, data->ln, ast_print_i);
|
||||||
|
|
||||||
|
INDENT_END;
|
||||||
|
}
|
||||||
|
41
src/dlist.c
Normal file
41
src/dlist.c
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#include "include/dlist.h"
|
||||||
|
#include "include/util.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
DList* dlist_init(void) {
|
||||||
|
DList* dlist = malloc(sizeof(DList));
|
||||||
|
|
||||||
|
dlist->sz = DLIST_INITSZ;
|
||||||
|
dlist->buf = malloc(DLIST_INITSZ);
|
||||||
|
dlist->ln = 0;
|
||||||
|
|
||||||
|
return dlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dlist_destroy(DList* dlist) {
|
||||||
|
free(dlist->buf);
|
||||||
|
free(dlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dlist_destroypsv(DList* dlist) { free(dlist); }
|
||||||
|
|
||||||
|
// Check whether the buffer is overflowing and resize it if necessary.
|
||||||
|
void check_resz(DList* dlist, size_t ln) {
|
||||||
|
while (dlist->ln + ln + 1 > dlist->sz) {
|
||||||
|
// Double the buffer size when overflown.
|
||||||
|
dlist->sz *= 2;
|
||||||
|
dlist->buf = realloc(dlist->buf, dlist->sz);
|
||||||
|
log_dbgf(
|
||||||
|
"dlist @ %p doubled from %ld to %ld", dlist, dlist->sz / 2, dlist->sz
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dlist_append(DList* dest, void* src) {
|
||||||
|
check_resz(dest, 1);
|
||||||
|
|
||||||
|
dest->buf[dest->ln] = src;
|
||||||
|
dest->ln += 1;
|
||||||
|
}
|
14
src/fnv1a.c
Normal file
14
src/fnv1a.c
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#include "include/fnv1a.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
uint64_t fnv1a_hash(char *key, size_t ln) {
|
||||||
|
uint64_t hash = FNV1A_BASIS_64;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ln; i++) {
|
||||||
|
hash ^= (unsigned char)key[i];
|
||||||
|
hash *= FNV1A_PRIME_64;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
@ -23,8 +23,11 @@
|
|||||||
|
|
||||||
%define parse.error verbose
|
%define parse.error verbose
|
||||||
|
|
||||||
%token LGROUP
|
%token BLOCKS
|
||||||
%token RGROUP
|
%token BLOCKE
|
||||||
|
|
||||||
|
%token GROUPS
|
||||||
|
%token GROUPE
|
||||||
%token SEP
|
%token SEP
|
||||||
|
|
||||||
%token EXPSEP
|
%token EXPSEP
|
||||||
@ -91,7 +94,7 @@ exp:
|
|||||||
$$ = ast_init(AST_TYPE_VREF, ast_vref_data_init($1));
|
$$ = ast_init(AST_TYPE_VREF, ast_vref_data_init($1));
|
||||||
}
|
}
|
||||||
|
|
||||||
| WORD LGROUP arg RGROUP {
|
| WORD GROUPS arg GROUPE {
|
||||||
size_t argc = $3->ln;
|
size_t argc = $3->ln;
|
||||||
AST** argv = $3->buf;
|
AST** argv = $3->buf;
|
||||||
argarr_destroypsv($3);
|
argarr_destroypsv($3);
|
||||||
|
38
src/htab.c
Normal file
38
src/htab.c
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#include "include/htab.h"
|
||||||
|
#include "include/fnv1a.h"
|
||||||
|
#include "include/util.h"
|
||||||
|
#include "include/util.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
HTab* htab_init() {
|
||||||
|
HTab* htab = calloc(1, sizeof(HTab));
|
||||||
|
|
||||||
|
return htab;
|
||||||
|
}
|
||||||
|
|
||||||
|
void htab_destroy(HTab *htab) {
|
||||||
|
free(htab);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the index of a key.
|
||||||
|
size_t geti(char* key) {
|
||||||
|
uint64_t hash = fnv1a_hash(key, strlen(key));
|
||||||
|
size_t i = hash & (HTAB_SPACE - 1);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* htab_get(HTab* htab, char* key) {
|
||||||
|
size_t i = geti(key);
|
||||||
|
log_dbgf("Getting something from hash table @ index %lu", i);
|
||||||
|
return (*htab)[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void htab_ins(HTab* htab, char* key, void* data) {
|
||||||
|
size_t i = geti(key);
|
||||||
|
assert((*htab)[i] == NULL);
|
||||||
|
(*htab)[i] = data;
|
||||||
|
log_dbgf("Inserted something to hash table @ index %lu", i);
|
||||||
|
}
|
@ -4,10 +4,11 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
AST_TYPE_NUM, // A number.
|
AST_TYPE_NUM, // A number.
|
||||||
AST_TYPE_CALL, // A function call.
|
AST_TYPE_CALL, // A function call.
|
||||||
AST_TYPE_VREF, // A variable reference.
|
AST_TYPE_VREF, // A variable reference.
|
||||||
AST_TYPE_MAX = AST_TYPE_CALL
|
AST_TYPE_BLOCK, // A block of code (scope).
|
||||||
|
AST_TYPE_MAX = AST_TYPE_BLOCK,
|
||||||
} ASTType;
|
} ASTType;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -44,4 +45,14 @@ ASTVrefData* ast_vref_data_init(char* to);
|
|||||||
void ast_vref_data_destroy(ASTVrefData* call);
|
void ast_vref_data_destroy(ASTVrefData* call);
|
||||||
void ast_vref_print(ASTVrefData*, int i);
|
void ast_vref_print(ASTVrefData*, int i);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
AST** inside; // What's inside the block.
|
||||||
|
size_t ln; // How many ASTs are in the block.
|
||||||
|
} ASTBlockData;
|
||||||
|
|
||||||
|
ASTBlockData* ast_block_data_init(AST** inside, size_t ln);
|
||||||
|
// Destroy a block. Also destroy all ASTs inside.
|
||||||
|
void ast_block_data_destroy(ASTBlockData* block);
|
||||||
|
void ast_block_data_print(ASTBlockData*, int i);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
22
src/include/dlist.h
Normal file
22
src/include/dlist.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#ifndef DLIST_H
|
||||||
|
#define DLIST_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define DLIST_INITSZ 128
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void** buf; // The buffer containing the list.
|
||||||
|
size_t sz; // The size of the buffer.
|
||||||
|
size_t ln; // The number of elements in the list.
|
||||||
|
} DList;
|
||||||
|
|
||||||
|
DList* dlist_init(void);
|
||||||
|
void dlist_destroy(DList* dstr);
|
||||||
|
// Destroy DList structure but preserve ->buf.
|
||||||
|
void dlist_destroypsv(DList* dstr);
|
||||||
|
|
||||||
|
// Append src to dest.
|
||||||
|
void dlist_append(DList* dest, void* src);
|
||||||
|
|
||||||
|
#endif
|
17
src/include/fnv1a.h
Normal file
17
src/include/fnv1a.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef FNV1A_H
|
||||||
|
#define FNV1A_H
|
||||||
|
|
||||||
|
// Implements the FNV-1a hash algorithm.
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// FNV prime.
|
||||||
|
#define FNV1A_PRIME_64 0x00000100000001b3u
|
||||||
|
|
||||||
|
// Offset basis.
|
||||||
|
#define FNV1A_BASIS_64 0xcbf29ce484222325u
|
||||||
|
|
||||||
|
uint64_t fnv1a_hash(char* str, size_t ln);
|
||||||
|
|
||||||
|
#endif
|
@ -2,25 +2,27 @@
|
|||||||
#define HTAB_H
|
#define HTAB_H
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#define HTAB_SPACE 128
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define HTAB_FN fnv1a_hash // Function used for hashing.
|
||||||
|
#define HTAB_SPACE 1024 // Number of entries possible in the hash table; must be
|
||||||
|
// power of 2.
|
||||||
|
|
||||||
// Hash Table.
|
// Hash Table.
|
||||||
typedef struct {} HTab;
|
typedef void* HTab[HTAB_SPACE];
|
||||||
|
|
||||||
// Create a new hash table.
|
// Create a new hash table.
|
||||||
HTab* htab_init();
|
HTab* htab_init();
|
||||||
// Destroy a hash table.
|
// Destroy a hash table, but not its elements.
|
||||||
void htab_destroy(HTab* htab);
|
void htab_destroy(HTab* htab);
|
||||||
|
|
||||||
// Get element at `hash`. Return its contents, or NULL if nothing found.
|
// Get element at `hash`. Return its contents, or NULL if nothing found.
|
||||||
void* htab_get(HTab* htab, int hash);
|
void* htab_get(HTab* htab, char* str);
|
||||||
|
|
||||||
// Insert `data` at index `hash`.
|
// Insert `data` at index `hash`.
|
||||||
void htab_ins(HTab* htab, int key, void* data);
|
void htab_ins(HTab* htab, char* key, void* data);
|
||||||
|
|
||||||
// Gets the length of the hash table.
|
// Gets the length of the hash table.
|
||||||
size_t htab_ln(HTab* htab);
|
size_t htab_ln(HTab* htab);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -113,6 +113,8 @@ int yylex() {
|
|||||||
case ')': return RGROUP;
|
case ')': return RGROUP;
|
||||||
case ',': return SEP;
|
case ',': return SEP;
|
||||||
case ';': return EXPSEP;
|
case ';': return EXPSEP;
|
||||||
|
case '{': return BLOCKS;
|
||||||
|
case '}': return BLOCKE;
|
||||||
default: fprintf(stderr, "Unexpected character: %c\n", c);
|
default: fprintf(stderr, "Unexpected character: %c\n", c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,8 +52,8 @@ void test_ast_vref() {
|
|||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
UNITY_BEGIN();
|
UNITY_BEGIN();
|
||||||
RUN_TEST(test_ast_num);
|
//RUN_TEST(test_ast_num);
|
||||||
RUN_TEST(test_ast_call);
|
//RUN_TEST(test_ast_call);
|
||||||
//RUN_TEST(test_ast_vref);
|
//RUN_TEST(test_ast_vref);
|
||||||
return UNITY_END();
|
return UNITY_END();
|
||||||
}
|
}
|
||||||
|
27
test/test_htab.c
Normal file
27
test/test_htab.c
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include "../src/include/htab.h"
|
||||||
|
#include "Unity/src/unity.h"
|
||||||
|
#include "Unity/src/unity_internals.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void setUp() {}
|
||||||
|
void tearDown() {}
|
||||||
|
|
||||||
|
void test_htab() {
|
||||||
|
char* key = "hello";
|
||||||
|
char* data = "world";
|
||||||
|
|
||||||
|
HTab* htab = htab_init();
|
||||||
|
|
||||||
|
htab_ins(htab, key, data);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_STRING(data, htab_get(htab, key));
|
||||||
|
TEST_ASSERT_NOT_EQUAL(data, htab_get(htab, "h"));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
UNITY_BEGIN();
|
||||||
|
|
||||||
|
RUN_TEST(test_htab);
|
||||||
|
|
||||||
|
return UNITY_END();
|
||||||
|
}
|
@ -95,3 +95,8 @@ bin() { ./scl.out $1 | tail -n1; }
|
|||||||
run bin "x = 1; x + 1"
|
run bin "x = 1; x + 1"
|
||||||
[ "$output" = "= 2.000000" ]
|
[ "$output" = "= 2.000000" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "function definition" {
|
||||||
|
run bin "f(n)=2*n; f(2)"
|
||||||
|
[ "$output" = "= 4.000000" ]
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user