start writing translator

This commit is contained in:
2025-06-13 02:46:42 +01:00
parent b05408ebec
commit 27a777ad86
15 changed files with 3356 additions and 32 deletions

3
.gitignore vendored
View File

@@ -52,7 +52,10 @@ Mkfile.old
dkms.conf
vcpkg_installed/
.venv
bin
build
*.yy.c
*.yy.h

60
CMakeLists.txt Normal file
View File

@@ -0,0 +1,60 @@
cmake_minimum_required(VERSION 3.16)
project(argon C)
# Conan will define FLEX_EXECUTABLE via an environment variable or toolchain
# You should set it in CMakeLists.txt only if it's not set
if(NOT DEFINED FLEX_EXECUTABLE)
find_program(FLEX_EXECUTABLE flex REQUIRED)
endif()
# Set source and output files
set(LEXER_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/lexer/lex.l)
set(LEXER_C ${CMAKE_CURRENT_SOURCE_DIR}/src/lexer/lex.yy.c)
set(LEXER_H ${CMAKE_CURRENT_SOURCE_DIR}/src/lexer/lex.yy.h)
# Gather all C files EXCEPT the generated lex.yy.c
file(GLOB_RECURSE CFILES CONFIGURE_DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/src/*.c
)
list(REMOVE_ITEM CFILES ${LEXER_C}) # remove if globbed
# Step 1: Custom command to generate lexer
add_custom_command(
OUTPUT ${LEXER_C} ${LEXER_H}
COMMAND ${FLEX_EXECUTABLE} --header-file=${LEXER_H} -o ${LEXER_C} ${LEXER_SRC}
DEPENDS ${LEXER_SRC}
COMMENT "Generating lexer with flex"
)
# Step 2: Custom target for lexer
add_custom_target(GenerateLexer DEPENDS ${LEXER_C} ${LEXER_H})
# Step 3: Add executable
add_executable(argon ${CFILES} ${LEXER_C})
# Step 4: Build order
add_dependencies(argon GenerateLexer)
# Step 5: Output path
set_target_properties(argon PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/build/bin
)
# Step 6: Conan libraries
find_package(BDWgc REQUIRED)
find_package(cJSON REQUIRED)
find_package(gmp REQUIRED)
target_compile_options(argon PRIVATE -O3 -Wall -Wextra -Wno-unused-function -s)
target_link_options(argon PRIVATE -static)
target_link_libraries(argon PRIVATE
BDWgc::BDWgc
cjson::cjson
gmp::gmp
m
)
target_include_directories(argon PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/lexer
)

9
CMakeUserPresets.json Normal file
View File

@@ -0,0 +1,9 @@
{
"version": 4,
"vendor": {
"conan": {}
},
"include": [
"build/CMakePresets.json"
]
}

View File

@@ -13,7 +13,7 @@ $(LEXER_C) $(LEXER_H): $(LEXER_SRC)
$(BINARY): $(CFILES) $(LEXER_C) $(LEXER_H)
mkdir -p bin
gcc -O3 -o $(BINARY) $(CFILES) $(CFLAGS) -s
gcc -static -O3 -o $(BINARY) $(CFILES) $(CFLAGS) -s
debug: $(CFILES) $(LEXER_C) $(LEXER_H)
mkdir -p bin
@@ -31,5 +31,5 @@ optimised: $(CFILES) $(LEXER_C) $(LEXER_H)
clean:
rm -rf bin
rm -rf build bin
rm -f $(LEXER_C) $(LEXER_H)

49
conanfile.py Normal file
View File

@@ -0,0 +1,49 @@
from conan import ConanFile
from conan.tools.cmake import CMake, CMakeToolchain, CMakeDeps, cmake_layout
from shutil import which
class ArgonConan(ConanFile):
name = "argon"
version = "1.0"
settings = "os", "compiler", "build_type", "arch"
generators = "CMakeDeps"
# Remove tool_requires, no flex from Conan
requires = [
"gmp/6.3.0",
"cjson/1.7.16",
"bdwgc/8.2.8"
]
default_options = {
"gmp/*:shared": False,
"cjson/*:shared": False,
"bdwgc/*:shared": False
}
def layout(self):
self.folders.source = "."
self.folders.build = "build"
self.folders.generators = "build"
def generate(self):
tc = CMakeToolchain(self)
# Try to find flex in system PATH first
flex_path = which("flex")
# If not found, fallback to flex from Conan build requirements
if not flex_path:
flex_dep = self.dependencies.build.get("flex", None)
if not flex_dep:
raise Exception("Flex not found in system PATH and not declared as build requirement")
flex_path = join(flex_dep.package_folder, "bin", "flex")
tc.variables["FLEX_EXECUTABLE"] = flex_path
tc.generate()
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()

BIN
out.car Normal file

Binary file not shown.

View File

@@ -3,10 +3,12 @@
#include "lexer/token.h"
#include "memory.h"
#include "parser/parser.h"
#include "translator/translator.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
if (argc <= 1)
@@ -34,6 +36,21 @@ int main(int argc, char *argv[]) {
parser(path, &ast, &tokens, false);
darray_free(&tokens, free_token);
Translated translated = init_translator();
translate(&translated, &ast);
darray_free(&ast, free_parsed);
file = fopen("out.car", "wb");
fwrite(&translated.registerCount, sizeof(size_t), 1, file);
fwrite(&translated.constants.size, sizeof(size_t), 1, file);
fwrite(&translated.bytecode.size, sizeof(size_t), 1, file);
fwrite(translated.constants.data, 1, translated.constants.size, file);
fclose(file);
free_translator(&translated);
return 0;
}

View File

@@ -188,6 +188,7 @@ void parser(char *file, DArray *parsed, DArray *tokens, bool inline_flag) {
}
void free_parsed(void *ptr) {
if (!ptr) {
fprintf(stderr, "panic: freeing NULL pointer\n");
exit(EXIT_FAILURE);

View File

@@ -0,0 +1,8 @@
#include "../translator.h"
#include <stddef.h>
#include <string.h>
void translate_parsed_string(Translated *translated, ParsedValue *parsedValue) {
size_t string_pos = arena_push_string(&translated->constants, (char*)parsedValue->data);
// set_registers(translated, 1);
}

View File

@@ -0,0 +1,7 @@
#ifndef STRING_H
#define STRING_H
#include "../translator.h"
void translate_parsed_string(Translated * translator, ParsedValue * parsedValue);
#endif

View File

@@ -1,14 +1,91 @@
#include "translator.h"
#include "../dynamic_array/darray.h"
#include "string/string.h"
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "../memory.h"
#include <string.h>
Translated *init_translator() {
Translated *translated = checked_malloc(sizeof(Translated));
if (!translated)
return NULL;
void arena_init(ConstantArena *arena) {
arena->data = checked_malloc(CHUNK_SIZE);
arena->capacity = CHUNK_SIZE;
arena->size = 0;
}
darray_init(&translated->bytecode, sizeof(uint8_t));
void arena_resize(ConstantArena *arena, size_t new_size) {
new_size = ((new_size / CHUNK_SIZE) + 1)*CHUNK_SIZE;
if (new_size == arena->capacity)
return;
arena->data = realloc(arena->data, new_size);
if (!arena->data) {
fprintf(stderr, "error: failed to resize arena from %zu to %zu\n", new_size, arena->capacity);
exit(EXIT_FAILURE);
}
arena->capacity = new_size;
}
void arena_free(ConstantArena *arena) {
free(arena->data);
arena->capacity = 0;
arena->size = 0;
}
void * arena_get(ConstantArena *arena, size_t offset) {
return arena->data + offset;
}
size_t arena_push_string(ConstantArena *arena, const char *string) {
size_t length = strlen(string)+1;
arena_resize(arena, arena->size+length);
size_t offset = arena->size;
strcpy(arena->data + arena->size, string);
arena->size += length;
return offset;
}
size_t arena_push(ConstantArena *arena, const void *data, size_t length) {
arena_resize(arena, arena->size+length);
size_t offset = arena->size;
memcpy(arena->data + arena->size, data, length);
arena->size += length;
return offset;
}
Translated init_translator() {
Translated translated;
darray_init(&translated.bytecode, sizeof(uint8_t));
arena_init(&translated.constants);
return translated;
}
size_t push_instruction_code(Translated * translator, size_t code) {
size_t offset = translator->bytecode.size;
darray_push(&translator->bytecode, &code);
return offset;
}
void set_registers(Translated * translator, size_t count) {
if (count>translator->registerCount) translator->registerCount = count;
}
void translate_parsed(Translated * translator, ParsedValue * parsedValue) {
switch (parsedValue->type) {
case AST_STRING:
translate_parsed_string(translator,parsedValue);
}
}
void translate(Translated * translator, DArray *ast) {
for (size_t i = 0; i<ast->size; i++) {
ParsedValue * parsedValue = darray_get(ast, i);
translate_parsed(translator,parsedValue);
}
}
void free_translator(Translated * translated) {
darray_free(&translated->bytecode, NULL);
arena_free(&translated->constants);
}

View File

@@ -3,12 +3,38 @@
#include "../dynamic_array/darray.h"
#include <stddef.h>
#include "../dynamic_array/darray.h"
#include "../parser/parser.h"
#include "../memory.h"
typedef enum { OP_INIT_STRING } OperationType;
typedef struct {
void *data;
size_t capacity;
size_t size;
} ConstantArena;
typedef struct {
size_t registerCount;
DArray bytecode;
ConstantArena constants;
} Translated;
void * arena_get(ConstantArena *arena, size_t offset);
size_t arena_push_string(ConstantArena *arena, const char *string);
size_t arena_push(ConstantArena *arena, const void *data, size_t length);
size_t push_instruction_code(Translated * translator, size_t code);
void set_registers(Translated * translator, size_t count);
Translated init_translator();
void translate(Translated * translator, DArray *ast);
void free_translator(Translated * translated);
#endif

3089
test.ar

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +0,0 @@
{
"default-registry": {
"kind": "git",
"baseline": "a9eee3b18df395dbb8be71a31bd78ea441056e42",
"repository": "https://github.com/microsoft/vcpkg"
},
"registries": [
{
"kind": "artifact",
"location": "https://github.com/microsoft/vcpkg-ce-catalog/archive/refs/heads/main.zip",
"name": "microsoft"
}
]
}

View File

@@ -1,6 +0,0 @@
{
"dependencies": [
"bdwgc",
"json-c"
]
}