Skip to content

Commit

Permalink
Remove embedding infrastructure
Browse files Browse the repository at this point in the history
  • Loading branch information
benanders committed Sep 22, 2018
1 parent e99e061 commit 08505fd
Show file tree
Hide file tree
Showing 19 changed files with 701 additions and 458 deletions.
56 changes: 37 additions & 19 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,40 @@ cmake_minimum_required(VERSION 3.6)
project(hydrogen)
set(CMAKE_C_STANDARD 99)

# Set the C compiler's debug and release flags
# Turn on all warnings for all C code
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")

# Turn off optimisations and add debugging symbols when in debug mode
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -g")

# Turn on all optimisations when in release mode
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3")
set(CMAKE_CXX_FLAGS "-Wno-c++11-compat-deprecated-writable-strings")

# Source files for the core library
set(VM_SOURCES
src/include/hydrogen.h
src/vm/vm.c src/vm/vm.h
src/vm/parser.c src/vm/parser.h
src/vm/lexer.c src/vm/lexer.h
src/vm/bytecode.h src/vm/value.h
src/vm/err.c src/vm/err.h
src/vm/util.c src/vm/util.h)
# Remove the annoying warning about type casting a `char *` string to a `const
# char *` in the C++ tests
set(CMAKE_CXX_FLAGS "-Wno-c++11-compat-deprecated-writable-strings")

# We split the interpreter up into a core library (hyvm) and a separate
# executable linked against this library (hydrogen) so that we can link the
# C++ tests against the core library, rather than having to re-compile all the
# source files again.
#
# Create the core VM library
add_library(hyvm STATIC ${VM_SOURCES})
target_include_directories(hyvm PUBLIC src/include)
add_library(hyvm STATIC
src/vm.c src/vm.h
src/parser.c src/parser.h
src/lexer.c src/lexer.h
src/bytecode.h src/value.h
src/util.c src/util.h)

# Create the CLI executable
set(CLI_SOURCES
src/include/hydrogen.h
src/cli/main.c)
add_executable(hydrogen ${CLI_SOURCES})
add_executable(hydrogen src/main.c)
target_link_libraries(hydrogen hyvm)

# Configure Google Test framework
# The tests use the C++ Google Test framework
add_subdirectory(tests/gtest)
enable_testing()
include_directories(${gtest_SOURCE_DIR}/include src/include src)
include_directories(${gtest_SOURCE_DIR}/include src)

# Macro for adding a test suite
macro(test name)
Expand All @@ -49,3 +52,18 @@ endmacro()
# Test suites
test(lexer)
test(parser)

# The runtime tests are run using a Python script, because that makes it easier
# to parse the expected output of the test straight from the .hy test file.
find_package(Python REQUIRED COMPONENTS Interpreter)

# Add runtime tests
#
# To run just the runtime tests, execute the following command from inside the
# build folder:
# $ python ../tests/runtime/test_runtime.py ../tests/runtime ./hydrogen
add_test(NAME test_runtime
COMMAND ${Python_EXECUTABLE}
${CMAKE_SOURCE_DIR}/tests/runtime/test_runtime.py
${CMAKE_SOURCE_DIR}/tests/runtime
${CMAKE_BINARY_DIR}/hydrogen)
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
The Hydrogen Programming Language
---------------------------------

Hydrogen is a **toy programming language** I'm writing mostly for my own edification. It's an **interpreted**, **dynamically typed** language written in C and hand-coded assembly. It comes with an **easy-to-use C API** for embedding within your own programs!
Hydrogen is a **toy programming language** I'm writing mostly for my own edification. It's an **interpreted**, **dynamically typed** language written in C. It's intended to be used as a standalone language, and not embedded within other programs.

The core is written in **C** and **hand-coded assembly**, with no dependencies beyond the C standard library. The tests are written in C++ using the [Google Test](https://github.com/google/googletest) framework.
The core is written in **C** with no dependencies beyond the C standard library. Most tests are written in C++ using the [Google Test](https://github.com/google/googletest) framework. The runtime tests are written using a custom Python script.

### Code Sample
### Example

Here's some Hydrogen code:

Expand Down
13 changes: 10 additions & 3 deletions src/vm/bytecode.h → src/bytecode.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,21 @@

#include <stdint.h>

// All bytecode opcodes. We can have up to 256 opcodes, since they must be
// storable in a single byte.
// All bytecode opcodes. We can have up to 256 opcodes, since they need to fit
// into a single byte.
//
// Meaning of the various suffixes:
// * N = number
// * P = primitive (false, true, nil)
// * F = function
// * NF = native function
typedef enum {
// Stores
OP_MOV,
OP_SET_N,
OP_SET_P,
OP_SET_F,
OP_SET_NF,

// Arithmetic operators
OP_ADD_LL,
Expand Down Expand Up @@ -75,7 +82,7 @@ typedef enum {
// String representation of each opcode.
static char * OPCODE_NAMES[] = {
// Stores
"OP_MOV", "OP_SET_N", "OP_SET_P", "OP_SET_F",
"OP_MOV", "OP_SET_N", "OP_SET_P", "OP_SET_F", "OP_SET_NF",

// Arithmetic operators
"OP_ADD_LL", "OP_ADD_LN", "OP_SUB_LL", "OP_SUB_LN", "OP_SUB_NL",
Expand Down
91 changes: 0 additions & 91 deletions src/include/hydrogen.h

This file was deleted.

14 changes: 7 additions & 7 deletions src/vm/lexer.c → src/lexer.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ static inline int is_ident_continue(char ch) {
}

// Creates a new lexer over the given source code.
Lexer lex_new(HyVM *vm, char *path, char *code) {
Lexer lex_new(VM *vm, char *path, char *code) {
Lexer lxr;
lxr.vm = vm;
lxr.path = path;
Expand Down Expand Up @@ -113,9 +113,9 @@ static void lex_int(Lexer *lxr, int base) {

// Check for a parse error
if (errno != 0) {
HyErr *err = err_new("failed to parse number");
Err *err = err_new("failed to parse number");
err->line = lxr->tk.line;
err_set_file(err, lxr->path);
err_file(err, lxr->path);
err_trigger(lxr->vm, err);
return;
}
Expand All @@ -139,9 +139,9 @@ static void lex_float(Lexer *lxr) {

// Check for a parse error
if (errno != 0) {
HyErr *err = err_new("failed to parse number");
Err *err = err_new("failed to parse number");
err->line = lxr->tk.line;
err_set_file(err, lxr->path);
err_file(err, lxr->path);
err_trigger(lxr->vm, err);
return;
}
Expand Down Expand Up @@ -274,9 +274,9 @@ char * tk_to_string(Tk *tk) {
// Triggers an error if the current token isn't what's expected.
void lex_expect(Lexer *lxr, Tk expected) {
if (lxr->tk.type != expected) {
HyErr *err = err_new("expected %s, found %s", tk_to_string(&expected),
Err *err = err_new("expected %s, found %s", tk_to_string(&expected),
tk_to_string(&lxr->tk.type));
err_set_file(err, lxr->path);
err_file(err, lxr->path);
err->line = lxr->tk.line;
err_trigger(lxr->vm, err);
}
Expand Down
4 changes: 2 additions & 2 deletions src/vm/lexer.h → src/lexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ typedef struct {

// Stores state information required by the lexer.
typedef struct {
HyVM *vm;
VM *vm;
char *path;
char *code;

Expand All @@ -68,7 +68,7 @@ typedef struct {

// Creates a new lexer over the given source code. If the code is from a file,
// the path to the file is also given (this can be NULL).
Lexer lex_new(HyVM *vm, char *path, char *code);
Lexer lex_new(VM *vm, char *path, char *code);

// Lexes the next token, storing the result in `lxr->tk`.
void lex_next(Lexer *lxr);
Expand Down
45 changes: 18 additions & 27 deletions src/cli/main.c → src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@
// July 2018
//

#include <hydrogen.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Only if colors are supported
#include "vm.h"

// Human-readable version string.
#define HY_VERSION_STRING "0.1.0"

// Only include if colors are supported
#if !defined(_WIN32) && !defined(_WIN64)
#include <unistd.h>
#endif
Expand Down Expand Up @@ -61,35 +65,22 @@ int run_repl() {
return 0;
}

// Run a source code string.
int run_string(char *code) {
HyVM *vm = hy_new_vm();
HyPkg pkg = hy_new_pkg(vm, NULL);
HyErr *err = hy_run_string(vm, pkg, code);

// Check for error
int return_code = 0;
if (err != NULL) {
hy_err_print(err, supports_color());
return_code = 1;
}
hy_free_vm(vm);
return return_code;
}

// Run a file.
int run_file(char *path) {
HyVM *vm = hy_new_vm();
HyErr *err = hy_run_file(vm, path);
// Create a new VM and run the file
VM vm = vm_new();
Err *err = vm_run_file(&vm, path);

// Check for error
int return_code = 0;
// Check for an error
if (err != NULL) {
hy_err_print(err, supports_color());
return_code = 1;
err_print(err, supports_color());
err_free(err);
vm_free(&vm);
return EXIT_FAILURE;
} else {
vm_free(&vm);
return EXIT_SUCCESS;
}
hy_free_vm(vm);
return return_code;
}

int main(int argc, char *argv[]) {
Expand Down
Loading

0 comments on commit 08505fd

Please sign in to comment.