~dvko/pepper-lang

8e4b228cbbc4daf1d478baa54440560408120005 — Danny van Kooten 3 months ago 37bbd03
address a bunch of compiler warnings related to signed comparision to unsigned types
9 files changed, 72 insertions(+), 84 deletions(-)

M Makefile
M src/builtins.c
M src/compiler.c
M src/opcode.c
M src/opcode.h
M src/parser.c
M src/pepper.c
M src/vm.c
M src/vm.h
M Makefile => Makefile +1 -1
@@ 1,4 1,4 @@
CFLAGS+= -std=c11 -Wall -Wpedantic -Wstringop-overflow=3 -Wvla -Wundef -Wextra -Isrc/ -g
CFLAGS+= -std=c11 -Wall -Wstringop-overflow=3 -Wvla -Wundef -Wextra -Isrc/ -g
VPATH= src
TESTS= bin/lexer_test bin/parser_test bin/opcode_test bin/compiler_test bin/vm_test bin/symbol_table_test


M src/builtins.c => src/builtins.c +13 -22
@@ 1,5 1,4 @@
#include <assert.h>
#include <stdarg.h>
#include <stdint.h>
#include <string.h> 
#include <stdio.h>


@@ 45,7 44,7 @@ struct object get_builtin_by_index(const uint8_t index) {
}

struct object get_builtin(const char* name) {
    for (int i = 0; i < sizeof(builtin_functions) / sizeof(builtin_functions[0]); i++) {
    for (unsigned i = 0; i < sizeof(builtin_functions) / sizeof(builtin_functions[0]); i++) {
        if (strcmp(name, builtin_functions[i].name) == 0) {
            return builtin_functions[i].fn_obj;
        }


@@ 59,13 58,12 @@ struct object get_builtin(const char* name) {

// defines built-in functions in compiler symbol table
void define_builtins(struct symbol_table* st) {
    for (int i = 0; i < sizeof(builtin_functions) / sizeof(builtin_functions[0]); i++) {
    for (unsigned i = 0; i < sizeof(builtin_functions) / sizeof(builtin_functions[0]); i++) {
        symbol_table_define_builtin_function(st, i, builtin_functions[i].name);
    }
}

static struct object 
builtin_len(const struct object_list* args) {
static struct object builtin_len(const struct object_list* args) {
    if (args->size != 1) {
        return make_error_object("wrong number of arguments: expected 1, got %d", args->size);
    }


@@ 87,9 85,8 @@ builtin_len(const struct object_list* args) {

}

static struct object 
builtin_print(const struct object_list* args) {
    for (uint32_t i=0; i < args->size; i++) {
static struct object builtin_print(const struct object_list* args) {
    for (unsigned i=0; i < args->size; i++) {
        print_object(args->values[i]);
    }



@@ 99,16 96,14 @@ builtin_print(const struct object_list* args) {
    };
}

static struct object 
builtin_type(const struct object_list *args) {
static struct object builtin_type(const struct object_list *args) {
    if (args->size != 1) {
        return make_error_object("wrong number of arguments: expected 1, got %d", args->size);
    }
    return make_string_object(object_type_to_str(args->values[0].type));
}

static struct object 
builtin_int(const struct object_list *args) {
static struct object builtin_int(const struct object_list *args) {
    if (args->size != 1) {
        return make_error_object("wrong number of arguments: expected 1, got %d", args->size);
    }


@@ 135,8 130,7 @@ builtin_int(const struct object_list *args) {
    return make_error_object("invalid object type");
}

static struct object 
builtin_array_pop(const struct object_list *args) {
static struct object builtin_array_pop(const struct object_list *args) {
    if (args->size != 1) {
        return make_error_object("wrong number of arguments: expected 1, got %d", args->size);
    }


@@ 154,8 148,7 @@ builtin_array_pop(const struct object_list *args) {
    return copy_object(&list->values[list->size-- - 1]);
}

static struct object 
builtin_array_push(const struct object_list *args) {
static struct object builtin_array_push(const struct object_list *args) {
    if (args->size != 2) {
        return make_error_object("wrong number of arguments: expected 2, got %d", args->size);
    }


@@ 171,8 164,7 @@ builtin_array_push(const struct object_list *args) {
    return make_integer_object(list->size);
}

static struct object 
builtin_file_get_contents(const struct object_list *args) {
static struct object builtin_file_get_contents(const struct object_list *args) {
    if (args->size != 1) {
        return make_error_object("wrong number of arguments: expected 1, got %d", args->size);
    }


@@ 193,7 185,7 @@ builtin_file_get_contents(const struct object_list *args) {

    struct object obj = make_string_object_with_length("", fsize);
    size_t bytes_read = fread(obj.value.string->value, 1, fsize, fd);
    assert(bytes_read >= 0);
    assert(bytes_read == fsize);
    obj.value.string->value[fsize] = '\0';
    fclose(fd);
    return obj;


@@ 238,8 230,7 @@ static struct object str_split(const struct object_list *args) {
  return make_array_object(list);
}

static struct object 
str_contains(const struct object_list *args) {
static struct object str_contains(const struct object_list *args) {
    if (args->size != 2) {
        return make_error_object("wrong number of arguments: expected 2, got %d", args->size);
    }


@@ 255,4 246,4 @@ str_contains(const struct object_list *args) {
    ret = strstr(subject, search);

    return make_boolean_object(ret != NULL);
}
\ No newline at end of file
}

M src/compiler.c => src/compiler.c +2 -2
@@ 25,7 25,7 @@ const uint16_t JUMP_PLACEHOLDER_CONTINUE = 9998;
static int compile_statement(struct compiler *compiler, const struct statement *statement);
static int compile_expression(struct compiler *compiler, const struct expression *expression);

struct compiler *compiler_new() {
struct compiler *compiler_new(void) {
    struct compiler *c = malloc(sizeof *c);
    assert(c != NULL);
    struct compiler_scope scope;


@@ 604,7 604,7 @@ compile_expression(struct compiler *c, const struct expression *expr) {
        break;

        case EXPR_ARRAY:
            for (int i=0; i < expr->array.size; i++) {
            for (unsigned i=0; i < expr->array.size; i++) {
                err = compile_expression(c, expr->array.values[i]);
                if (err) return err;
            }

M src/opcode.c => src/opcode.c +12 -14
@@ 45,13 45,11 @@ const struct definition definitions[] = {
    { "OpHalt", 0, {0}, },
};

inline const 
char *opcode_to_str(enum opcode opcode) {
inline const char *opcode_to_str(enum opcode opcode) {
    return definitions[opcode].name;
}

inline const
struct definition lookup(enum opcode opcode) {
inline struct definition lookup(enum opcode opcode) {
    return definitions[opcode];
}



@@ 102,19 100,19 @@ struct instruction *copy_instructions(const struct instruction *a) {
    return b;
}

struct instruction *flatten_instructions_array(struct instruction *arr[], const uint32_t size) {
struct instruction *flatten_instructions_array(struct instruction *arr[], const unsigned size) {
    struct instruction *ins = arr[0];

    // reallocate to fit all bytecode 
    int32_t totalsize = 0;
    for (int32_t i=0; i < size; i++) {
    unsigned totalsize = 0;
    for (unsigned i=0; i < size; i++) {
        totalsize += arr[i]->size;
    }
    ins->bytes = realloc(ins->bytes, totalsize);
    assert(ins->bytes != NULL);

    // add all instructions to first instruction in the list
    for (uint32_t i = 1; i < size; i++) {        
    for (unsigned i = 1; i < size; i++) {
        memcpy(ins->bytes + ins->size, arr[i]->bytes, arr[i]->size);
        ins->size += arr[i]->size;
        free_instruction(arr[i]);


@@ 126,12 124,12 @@ struct instruction *flatten_instructions_array(struct instruction *arr[], const 
char *instruction_to_str(struct instruction *ins) {
    char *buffer = malloc(ins->size * 32);
    assert(buffer != NULL);
    uint32_t operands[MAX_OP_SIZE] = {0, 0};
    unsigned operands[MAX_OP_SIZE] = {0, 0};
    buffer[0] = '\0';

    for (uint32_t i=0; i < ins->size; i++) {
    for (unsigned i=0; i < ins->size; i++) {
        struct definition def = lookup(ins->bytes[i]);
        uint32_t bytes_read = read_operands(operands, def, ins, i);
        unsigned bytes_read = read_operands(operands, def, ins, i);
        
        if (i > 0) {
            strcat(buffer, " | ");


@@ 156,8 154,8 @@ char *instruction_to_str(struct instruction *ins) {
    return buffer;
}

uint32_t read_operands(uint32_t dest[], struct definition def, const struct instruction *ins, uint32_t offset) {
    uint32_t bytes_read = 0;
unsigned read_operands(unsigned dest[], struct definition def, const struct instruction *ins, uint32_t offset) {
    unsigned bytes_read = 0;

    // skip opcode
    offset += 1;


@@ 176,4 174,4 @@ uint32_t read_operands(uint32_t dest[], struct definition def, const struct inst
    }

    return bytes_read;
}
\ No newline at end of file
}

M src/opcode.h => src/opcode.h +5 -5
@@ 54,8 54,8 @@ struct definition {

struct instruction {
    uint8_t *bytes;
    uint32_t cap;
    uint32_t size;
    unsigned cap;
    unsigned size;
};

struct bytecode {


@@ 64,11 64,11 @@ struct bytecode {
};

const char *opcode_to_str(enum opcode opcode);
const struct definition lookup(enum opcode opcode);
struct definition lookup(enum opcode opcode);
struct instruction *make_instruction(enum opcode opcode, ...);
struct instruction *make_instruction_va(enum opcode opcode, va_list operands);
struct instruction *copy_instructions(const struct instruction *a);
void free_instruction(struct instruction *ins);
struct instruction *flatten_instructions_array(struct instruction *arr[], uint32_t size);
struct instruction *flatten_instructions_array(struct instruction *arr[], unsigned size);
char *instruction_to_str(struct instruction *ins);
uint32_t read_operands(uint32_t dest[], struct definition def, const struct instruction *ins, uint32_t offset);
\ No newline at end of file
unsigned read_operands(unsigned dest[], struct definition def, const struct instruction *ins, uint32_t offset);

M src/parser.c => src/parser.c +17 -19
@@ 9,17 9,11 @@
#include "lexer.h"
#include "util.h"

static struct expression *parse_expression(struct parser *p, int8_t precedence);
static int parse_statement(struct parser *p, struct statement *s);
static void expression_to_str(char *str, const struct expression *expr);
static void free_expression(struct expression *expr);
static enum operator parse_operator(enum token_type t);
void free_parser(struct parser* p);

enum precedence {
    LOWEST = 1,
    ASSIGN,
    LOGICAL_OR,   
    LOGICAL_OR,
    LOGICAL_AND,
    EQUALS,         // ==
    LESSGREATER,    // < or >


@@ 30,9 24,15 @@ enum precedence {
    INDEX,          // array[i]
};

static struct expression *parse_expression(struct parser *p, enum precedence precedence);
static int parse_statement(struct parser *p, struct statement *s);
static void expression_to_str(char *str, const struct expression *expr);
static void free_expression(struct expression *expr);
static enum operator parse_operator(enum token_type t);
void free_parser(struct parser* p);

static 
enum precedence 
get_token_precedence(const struct token t) {
enum precedence get_token_precedence(const struct token t) {
    switch (t.type) {
        default: 
            return LOWEST;


@@ 79,8 79,7 @@ struct parser new_parser(struct lexer *l) {
        .lexer = l,
        .errors = 0,
    };
    p.error_messages = malloc(0);
    assert(p.error_messages != NULL);
    p.error_messages = NULL;

    // read two tokens so that both current_token and next_token are set
    gettoken(p.lexer, &p.current_token);


@@ 451,7 450,7 @@ struct expression *parse_grouped_expression(struct parser *p) {
}

static struct block_statement* 
create_block_statement(uint32_t cap) {
create_block_statement(unsigned cap) {
    struct block_statement *b = (struct block_statement *) malloc(sizeof *b);
    assert(b != NULL);
    b->cap = cap;


@@ 676,8 675,7 @@ struct expression *parse_function_literal(struct parser *p) {
    return expr;
}

static struct expression *
parse_expression(struct parser *p, const int8_t precedence) {
static struct expression *parse_expression(struct parser *p, const enum precedence precedence) {
    struct expression *left;
    switch (p->current_token.type) {
        case TOKEN_IDENT: 


@@ 897,13 895,13 @@ void statement_to_str(char *str, const struct statement *stmt) {
}

void block_statement_to_str(char *str, const struct block_statement *b) {
    for (int32_t i=0; i < b->size; i++) {
    for (unsigned i=0; i < b->size; i++) {
        statement_to_str(str, &b->statements[i]);
    }
}

void identifier_list_to_str(char *str, const struct identifier_list *identifiers) {
    for (int32_t i=0; i < identifiers->size; i++) {
    for (unsigned i=0; i < identifiers->size; i++) {
        if (i > 0) {
            strcat(str, ", ");
        }


@@ 1006,7 1004,7 @@ void expression_to_str(char *str, const struct expression *expr) {
        case EXPR_CALL:
            expression_to_str(str, expr->call.function);
            strcat(str, "(");
            for (int32_t i=0; i < expr->call.arguments.size; i++){
            for (unsigned i=0; i < expr->call.arguments.size; i++){
                expression_to_str(str, expr->call.arguments.values[i]);
                if (i < (expr->call.arguments.size - 1)) {
                    strcat(str, ", ");


@@ 1017,7 1015,7 @@ void expression_to_str(char *str, const struct expression *expr) {

        case EXPR_ARRAY: 
            strcat(str, "[");
            for (int32_t i=0; i < expr->array.size; i++) {
            for (unsigned i=0; i < expr->array.size; i++) {
                expression_to_str(str, expr->array.values[i]);

                if (i < (expr->array.size - 1)) {


@@ 1228,7 1226,7 @@ void free_expression(struct expression *expr) {
}

void free_parser(struct parser* p) {
    for (int i=0; i < p->errors; i++) {
    for (unsigned i=0; i < p->errors; i++) {
        free(p->error_messages[i]);
    }
    free(p->error_messages);

M src/pepper.c => src/pepper.c +6 -6
@@ 40,12 40,12 @@ static
char *read_file(const char *filename);

static
void print_version() {
void print_version(void) {
	printf("Pepper v%d.%d.%d\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH);
}

static 
int repl() {
int repl(void) {
	print_version();
	printf("Press CTRL+c to exit\n\n");
	struct program *program;


@@ 66,7 66,7 @@ int repl() {

		if (parser.errors > 0) {
			printf("Parsing error:\n");
			for (int i = 0; i < parser.errors; i++) {
			for (unsigned i = 0; i < parser.errors; i++) {
				printf("- %s\n", parser.error_messages[i]);
			}



@@ 95,7 95,7 @@ int repl() {
		}

		// copy globals out of VM so we can re-use them in next iteration
		for (int32_t i=0; i < GLOBALS_SIZE; i++) {
		for (unsigned i=0; i < GLOBALS_SIZE; i++) {
			globals[i] = machine->globals[i];
		}



@@ 117,7 117,7 @@ int run_script(const char *filename) {
	struct program *program = parse_program(&parser);

	if (parser.errors > 0) {
		for (int8_t i = 0; i < parser.errors; i++) {
		for (unsigned i = 0; i < parser.errors; i++) {
			puts(parser.error_messages[i]);
		}



@@ 184,4 184,4 @@ char *read_file(const char *filename) {

	fclose(f);
	return input;
}
\ No newline at end of file
}

M src/vm.c => src/vm.c +9 -8
@@ 46,14 46,14 @@ print_debug_info(struct vm *vm) {
    }

    printf("Constants: \n");
    for (int i = 0; i < vm->nconstants; i++) {
    for (unsigned i = 0; i < vm->nconstants; i++) {
        str[0] = '\0';
        object_to_str(str, vm->constants[i]);
        printf("  %3d: %s = %s\n", i, object_type_to_str(vm->constants[i].type), str);
    }

    printf("Globals: \n");
    for (int i = 0; i < GLOBALS_SIZE; i++) {
    for (unsigned i = 0; i < GLOBALS_SIZE; i++) {
        if (vm->globals[i].type == OBJ_NULL) {
            break;
        }


@@ 63,7 63,7 @@ print_debug_info(struct vm *vm) {
    }

    printf("Stack: \n");
    for (int i=0; i < vm->stack_pointer; i++) {
    for (unsigned i=0; i < vm->stack_pointer; i++) {
        str[0] = '\0';
        object_to_str(str, vm->stack[i]);
        printf("  %3d: %s = %s\n", i, object_type_to_str(vm->stack[i].type), str);


@@ 80,13 80,13 @@ struct vm *vm_new(struct bytecode *bc) {
    vm->frame_index = 0;

    // initialize globals as null objects for print_debug_info()
    for (int32_t i=0; i < GLOBALS_SIZE; i++) {
    for (unsigned i=0; i < GLOBALS_SIZE; i++) {
        vm->globals[i].type = OBJ_NULL;
    }

    // copy over constants from compiled bytecode
    vm->nconstants = 0;
    for (int32_t i=0; i < bc->constants->size; i++) {
    for (unsigned i=0; i < bc->constants->size; i++) {
       vm->constants[vm->nconstants++] = bc->constants->values[i];
    }    



@@ 106,7 106,7 @@ struct vm *vm_new(struct bytecode *bc) {
struct vm *vm_new_with_globals(struct bytecode *bc, struct object globals[GLOBALS_SIZE]) {
    struct vm *vm = vm_new(bc);

    for (int32_t i=0; i < GLOBALS_SIZE; i++) {
    for (unsigned i=0; i < GLOBALS_SIZE; i++) {
        vm->globals[i] = globals[i];
    }
    return vm;


@@ 385,6 385,7 @@ vm_build_array(struct vm* restrict vm, uint16_t start_index, uint16_t end_index)

static struct object build_slice_from_array(struct object_list* source, int32_t start, int32_t end)
{

    if (start < 0) {
        start = source->size + start;
    }


@@ 395,7 396,7 @@ static struct object build_slice_from_array(struct object_list* source, int32_t 
        end = start;
    }
    struct object_list* list = make_object_list(end - start);
    for (int i=start; i < end && i < source->size; i++) {
    for (int i=start; i < end && i < (int) source->size; i++) {
        list->values[list->size++] = source->values[i];
    }
    return make_array_object(list);


@@ 415,7 416,7 @@ static struct object build_slice_from_string(struct string* source, int32_t star
    struct object obj = make_string_object_with_length("", end - start);
    struct string* str = obj.value.string;
    str->length = 0;
    for (int i=start; i < end && i < source->length; i++) {
    for (int i=start; i < end && i < (int) source->length; i++) {
        str->value[str->length++] = source->value[i];
    }
    str->value[str->length] = '\0';

M src/vm.h => src/vm.h +7 -7
@@ 4,9 4,9 @@
#include "opcode.h"
#include "object.h"

#define FRAMES_SIZE 64
#define GLOBALS_SIZE 64
#define STACK_SIZE 256
#define FRAMES_SIZE 64u
#define GLOBALS_SIZE 64u
#define STACK_SIZE 256u

enum result {
    VM_SUCCESS = 0,


@@ 21,13 21,13 @@ enum result {
struct frame {
    uint8_t *ip;
    struct compiled_function* fn;
    uint32_t base_pointer;    
    unsigned base_pointer;
};

struct vm {
    uint32_t stack_pointer;
    uint32_t frame_index;
    uint32_t nconstants;
    unsigned stack_pointer;
    unsigned frame_index;
    unsigned nconstants;
    struct object stack[STACK_SIZE];
    struct object constants[GLOBALS_SIZE];
    struct frame frames[FRAMES_SIZE];