diff --git a/Dockerfile b/Dockerfile index 3fc24fb..4263704 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,6 +10,7 @@ COPY --chown=lorang CMakeLists.txt /home/lorang/ COPY --chown=lorang run-check-test.sh /home/lorang/ COPY --chown=lorang .env /home/lorang/ COPY --chown=lorang run-docker-build.sh /home/lorang/ +COPY --chown=lorang run-lib-build.sh /home/lorang/ COPY --chown=lorang dep /home/lorang/dep COPY --chown=lorang .git /home/lorang/.git diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt new file mode 100644 index 0000000..6bc0d38 --- /dev/null +++ b/lib/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.15...3.25) + +project(gemstone_stdlib + VERSION 0.1.0 + DESCRIPTION "gemstone programming language standard library" + LANGUAGES C) + +set(CMAKE_C_STANDARD 23) +set(CMAKE_C_STANDARD_REQUIRED TRUE) + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +include_directories(${PROJECT_SOURCE_DIR}/src) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/../bin/std") + +# add native module libraries + +file(GLOB_RECURSE STDLIB_IO_SOURCE_FILES src/io/*.c) +add_library(io ${STDLIB_IO_SOURCE_FILES}) + +file(GLOB_RECURSE STDLIB_MEM_SOURCE_FILES src/mem/*.c) +add_library(mem ${STDLIB_MEM_SOURCE_FILES}) + +file(GLOB_RECURSE STDLIB_OS_SOURCE_FILES src/os/*.c) +add_library(os ${STDLIB_OS_SOURCE_FILES}) \ No newline at end of file diff --git a/lib/build.toml b/lib/build.toml new file mode 100644 index 0000000..85c5687 --- /dev/null +++ b/lib/build.toml @@ -0,0 +1,16 @@ +[project] +name = "gemstone standard library" +version = "0.1.0" +description = "Cross platform standard library for thr gemstone programming language." +license = "GPL-2.0" +authors = [ "Sven Vogel " ] + +[target.release] +root = "src/std.gem" +mode = "library" +output = "bin" +archive = "archive" +print_ast = false +print_asm = false +print_ir = false +opt = 3 diff --git a/lib/src/bool.gem b/lib/src/bool.gem new file mode 100644 index 0000000..e028294 --- /dev/null +++ b/lib/src/bool.gem @@ -0,0 +1,7 @@ + +import "def.gem" + +type unsigned int: bool + +static bool: TRUE = 1 +static bool: FALSE = 0 diff --git a/lib/src/capi.h b/lib/src/capi.h new file mode 100644 index 0000000..0ef22ab --- /dev/null +++ b/lib/src/capi.h @@ -0,0 +1,14 @@ +// +// Created by servostar on 6/3/24. +// + +#ifndef GEMSTONE_STD_LIB_CAPI_H +#define GEMSTONE_STD_LIB_CAPI_H + +#if defined(_WIN32) || defined (_WIN64) +#define PLATFORM_WINDOWS +#elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__linux__) +#define PLATFORM_POSIX +#endif + +#endif // GEMSTONE_STD_LIB_CAPI_H diff --git a/lib/src/def.gem b/lib/src/def.gem new file mode 100644 index 0000000..5bd344f --- /dev/null +++ b/lib/src/def.gem @@ -0,0 +1,38 @@ +# Author: Sven Vogel +# Edited: 25.05.2024 +# License: GPL-2.0 + +# ,----------------------------------------. +# | Standard Type definitions | +# `----------------------------------------` + +# Unsigned integrals + +type unsgined half half int: u8 +type unsgined half int: u16 +type unsgined int: u32 +type unsgined double int: u64 +type unsgined double double int: u128 + +# Signed integrals + +type signed u8: i8 +type signed u16: i16 +type signed u32: i32 +type signed u64: i64 +type signed u128: i128 + +# IEEE-754 floating point + +type signed half float: f16 +type signed float: f32 +type signed double float: f64 +type signed double double float: f128 + +# String constant + +type ref u8: cstr + +# C style void pointer replacement + +type ref u8: ptr diff --git a/lib/src/def/api.h b/lib/src/def/api.h new file mode 100644 index 0000000..a807865 --- /dev/null +++ b/lib/src/def/api.h @@ -0,0 +1,28 @@ +// Author: Sven Vogel +// Edited: 25.05.2024 +// License: GPL-2.0 + +#ifndef GEMSTONE_STD_LIB_DEF_H_ +#define GEMSTONE_STD_LIB_DEF_H_ + +#include +#include + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +typedef int8_t i8; +typedef int16_t i16; +typedef int32_t i32; +typedef int64_t i64; + +typedef float f32; +typedef double f64; + +typedef u8* cstr; + +typedef u8* ptr; + +#endif // GEMSTONE_STD_LIB_DEF_H_ diff --git a/lib/src/io.gem b/lib/src/io.gem new file mode 100644 index 0000000..bc2c553 --- /dev/null +++ b/lib/src/io.gem @@ -0,0 +1,53 @@ +# Author: Sven Vogel +# Edited: 25.05.2024 +# License: GPL-2.0 + +# ,----------------------------------------. +# | Generic Input/Output | +# `----------------------------------------` + +import "def.gem" + +# platform specific handle to an I/O device +# can a file, buffer, window or something else +# NOTE: this reference is not meant to be dereferenced +# which can lead to errors and undefined behavior +type ptr: handle + +# Returns a handle to this processes standard input I/O handle +# -- Implementation note +# On Linux this will return 0 as is it convention under UNIX (see: https://www.man7.org/linux/man-pages/man3/stdin.3.html) +# On Windows the library will call `GetStdHandle(STD_INPUT_HANDLE)` +fun getStdinHandle(out handle: stdin) + +# Returns a handle to this processes standard input I/O handle +# -- Implementation note +# On Linux this will return 1 as is it convention under UNIX (see: https://www.man7.org/linux/man-pages/man3/stdout.3.html) +# On Windows the library will call `GetStdHandle(STD_OUTPUT_HANDLE)` +fun getStdoutHandle(out handle: stdout) + +# Returns a handle to this processes standard input I/O handle +# -- Implementation note +# On Linux this will return 1 as is it convention under UNIX (see: https://www.man7.org/linux/man-pages/man3/stderr.3.html) +# On Windows the library will call `GetStdHandle(STD_OUTPUT_HANDLE)` +fun getStderrHandle(out handle: stderr) + +# Write `len` number of bytes from `buf` into the I/O resource specified +# by `dev`. Returns the number of bytes written. +# -- Implementation note +# On Linux this will use the syscall write +# On Windows this will use the WriteFile function +fun writeBytes(in handle: dev, in ref u8: buf, in ref u32: len)(out u32: written) + +# Read atmost `len` bytes to `buf` from the I/O resource specified by `dev` +# Returns the number of read bytes in `written` +# -- Implementation note +# On Linux this will use the syscall read +# On Windows this will use the ReadFile function +fun readBytes(in handle: dev, in ref u8: buf, in ref u32: len)(out u32: read) + +# Flushes the buffers of the I/O resource specified by `dev` +# -- Implementation note +# On Linux this will use the fsync function +# On Windows this will use the FlushFileBuffers function +fun flush(in handle: dev) diff --git a/lib/src/io/api.h b/lib/src/io/api.h new file mode 100644 index 0000000..c642185 --- /dev/null +++ b/lib/src/io/api.h @@ -0,0 +1,21 @@ + +#ifndef GEMSTONE_STD_LIB_IO_H_ +#define GEMSTONE_STD_LIB_IO_H_ + +#include + +typedef ptr handle; + +void getStdinHandle(handle* stdin); + +void getStdoutHandle(handle* stdout); + +void getStderrHandle(handle* stderr); + +void writeBytes(handle dev, u8* buf, u32 len, u32* written); + +void readBytes(handle dev, u8* buf, u32 len, u32* read); + +void flush(handle dev); + +#endif //GEMSTONE_STD_LIB_IO_H_ diff --git a/lib/src/io/impl.c b/lib/src/io/impl.c new file mode 100644 index 0000000..f56c561 --- /dev/null +++ b/lib/src/io/impl.c @@ -0,0 +1,74 @@ + +#include +#include + +#if defined(PLATFORM_WINDOWS) + +// Compile for Windows + +#include + +// FIXME: error in case GetStdHandle return INVALID_HANDLE_VALUE +// FIXME: error in case functions return 0 + +void getStdinHandle(handle* stdin) { + *stdin = (handle) GetStdHandle(STD_INPUT_HANDLE); +} + +void getStdoutHandle(handle* stdout) { + *stdout = (handle) GetStdHandle(STD_OUTPUT_HANDLE); +} + +void getStderrHandle(handle* stderr) { + *stderr = (handle) GetStdHandle(STD_ERROR_HANDLE); +} + +void writeBytes(handle dev, u8* buf, u32 len, u32* bytesWritten) { + WriteFile((HANDLE) dev, buf, len, bytesRead, NULL); +} + +void readBytes(handle dev, u8* buf, u32 len, u32* bytesRead) { + ReadFile((HANDLE) dev, buf, len, bytesRead, NULL); +} + +void flush(handle dev) { + FlushFileBuffers((HANDLE) dev); +} + +#elif defined(PLATFORM_POSIX) + +// Compile for Linux and BSD + +#include + +// savely cast a 64-bit pointer down to a 32-bit value +// this assumes that 64-bit system will use 32-bit handles +// which are stored as 64-bit by zero extending +#define TO_INT(x) ((int)(long int)(x)) + +void getStdinHandle(handle* stdin) { + *stdin = (handle) STDIN_FILENO; +} + +void getStdoutHandle(handle* stdout) { + *stdout = (handle) STDOUT_FILENO; +} + +void getStderrHandle(handle* stderr) { + *stderr = (handle) STDERR_FILENO; +} + +void writeBytes(handle dev, u8* buf, u32 len, u32* bytesWritten) { + *bytesWritten = write(TO_INT(dev), buf, len); +} + +void readBytes(handle dev, u8* buf, u32 len, u32* bytesRead) { + *bytesRead = read(TO_INT(dev), buf, len); +} + +void flush(handle dev) { + fsync(TO_INT(dev)); +} + + +#endif diff --git a/lib/src/mem.gem b/lib/src/mem.gem new file mode 100644 index 0000000..faecbc4 --- /dev/null +++ b/lib/src/mem.gem @@ -0,0 +1,27 @@ +# Author: Sven Vogel +# Edited: 25.05.2024 +# License: GPL-2.0 + +# ,----------------------------------------. +# | Memory Management | +# `----------------------------------------` + +import "def.gem" + +# Allocate `len` bytes of heap memory +# Returns a pointer to the memory as `ptr` +fun heap_alloc(in u32: len)(out ref u8: ptr) + +# Rellocate `len` bytes of heap memory +# Returns a pointer to the memory as `ptr` +fun heap_realloc(in u32: len, in out ref u8: ptr) + +# Free a block of memory +fun heap_free(in ref u8: ptr) + +# Copy `len` bytes from `dst` into `src` +fun copy(in ref u8: dst, in ref u8: src, in u32 len) + +# Fill `len` bytes of `dst` with `byte` +fun fill(in ref u8: dst, in u8: byte, in u32 len) + diff --git a/lib/src/mem/api.h b/lib/src/mem/api.h new file mode 100644 index 0000000..8ca69c0 --- /dev/null +++ b/lib/src/mem/api.h @@ -0,0 +1,17 @@ + +#ifndef GEMSTONE_STD_LIB_MEM_H_ +#define GEMSTONE_STD_LIB_MEM_H_ + +#include + +void heap_alloc(u32 len, u8** ptr); + +void heap_realloc(u32 len, u8** ptr); + +void heap_free(u8* ptr); + +void copy(u8* dst, u8* src, u32 len); + +void fill(u8* dst, u8 byte, u32 len); + +#endif // GEMSTONE_STD_LIB_MEM_H_ diff --git a/lib/src/mem/impl.c b/lib/src/mem/impl.c new file mode 100644 index 0000000..9d384a8 --- /dev/null +++ b/lib/src/mem/impl.c @@ -0,0 +1,52 @@ + +#include +#include + +#if defined(PLATFORM_WINDOWS) + +#include + +#define HEAP_API_GLOBAL_FLAGS HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS + +void heap_alloc(u32 len, u8** ptr) { + HANDLE heap = GetProcessHeap(); + *ptr = HeapAlloc(heap, HEAP_API_GLOBAL_FLAGS, len); +} + +void heap_realloc(u32 len, u8** ptr) { + HANDLE heap = GetProcessHeap(); + *ptr = HeapReAlloc(heap, HEAP_API_GLOBAL_FLAGS, *ptr, len); +} + +void heap_free(u8* ptr) { + HANDLE heap = GetProcessHeap(); + HeapFree(heap, ptr); +} + +#elif defined(PLATFORM_POSIX) + +#include + +void heap_alloc(u32 len, u8** ptr) { + *ptr = malloc(len); +} + +void heap_realloc(u32 len, u8** ptr) { + *ptr = realloc(*ptr, len); +} + +void heap_free(u8* ptr) { + free(ptr); +} + +#endif + +#include + +void copy(u8* dst, u8* src, u32 len) { + memcpy(dst, src, len); +} + +void fill(u8* dst, u8 byte, u32 len) { + memset(dst, byte, len); +} \ No newline at end of file diff --git a/lib/src/os.gem b/lib/src/os.gem new file mode 100644 index 0000000..9f51a45 --- /dev/null +++ b/lib/src/os.gem @@ -0,0 +1,25 @@ +# Author: Sven Vogel +# Edited: 03.06.2024 +# License: GPL-2.0 + +# ,----------------------------------------. +# | Operating System | +# `----------------------------------------` + +import "def.gem" + +# Return a hard coded C string identifying the underlying operating system +# Will return one of the following: +# - "windows" (for Windows 7, Windows 10 and Windows 11) +# - "unix" (for GNU/Linux and BSD) +fun getPlatformName(out cstr: name) + +# Return a C string to the value of an environment varible named +# after the C string name. +fun getEnvVar(in cstr: name)(out cstr: value) + +# Set the value of an environment variable with name to value. +fun setEnvVar(in cstr: name, in cstr: value) + +# Unset a specific environment variable +fun unsetEnvVar(in cstr: name) \ No newline at end of file diff --git a/lib/src/os/api.h b/lib/src/os/api.h new file mode 100644 index 0000000..3ed7a1f --- /dev/null +++ b/lib/src/os/api.h @@ -0,0 +1,18 @@ +// +// Created by servostar on 6/3/24. +// + +#ifndef GEMSTONE_STD_LIB_OS_H +#define GEMSTONE_STD_LIB_OS_H + +#include + +void getPlatformName(cstr* name); + +void getEnvVar(cstr name, cstr* value); + +void setEnvVar(cstr name, cstr value); + +void unsetEnvVar(cstr name); + +#endif // GEMSTONE_STD_LIB_OS_H diff --git a/lib/src/os/impl.c b/lib/src/os/impl.c new file mode 100644 index 0000000..7bed097 --- /dev/null +++ b/lib/src/os/impl.c @@ -0,0 +1,36 @@ +// +// Created by servostar on 6/3/24. +// + +#include +#include + +#if defined(PLATFORM_WINDOWS) + +void getPlatformName(cstr* name) { + *name = (u8*) "windows"; +} + +#elif defined(PLATFORM_POSIX) + +void getPlatformName(cstr * name) { + *name = (u8*) "posix"; +} + +#endif + +// Implementation based on libc + +#include + +void getEnvVar(cstr name, cstr* value) { + *value = (cstr) getenv((char*) name); +} + +void setEnvVar(cstr name, cstr value) { + setenv((char*) name, (char*) value, true); +} + +void unsetEnvVar(cstr name) { + unsetenv((char*) name); +} diff --git a/lib/src/std.gem b/lib/src/std.gem new file mode 100644 index 0000000..e135a13 --- /dev/null +++ b/lib/src/std.gem @@ -0,0 +1,16 @@ +# Author: Sven Vogel +# Edited: 25.05.2024 +# License: GPL-2.0 + +# ,----------------------------------------. +# | Gemstone Standard Library | +# `----------------------------------------` + +# standard type definitions +import "def.gem" + +# I/O operations +import "io.gem" + +# memory management +import "mem.gem" diff --git a/run-check-test.sh b/run-check-test.sh index a20f2ad..1acba79 100644 --- a/run-check-test.sh +++ b/run-check-test.sh @@ -17,6 +17,8 @@ if [ ! $? -eq 0 ]; then exit 1 fi +sh -c ./run-lib-build.sh + echo "+--------------------------------------+" echo "| RUNNING CODE CHECK |" echo "+--------------------------------------+" diff --git a/run-lib-build.sh b/run-lib-build.sh new file mode 100755 index 0000000..ccca62c --- /dev/null +++ b/run-lib-build.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +# Author: Sven Vogel +# Created: 25.05.2024 +# Description: Builds the standard library into bin/std + +echo "+--------------------------------------+" +echo "| CONFIGURE STD LIBRARY |" +echo "+--------------------------------------+" + +cmake lib +if [ ! $? -eq 0 ]; then + echo "===> failed to configure build" + exit 1 +fi + +echo "+--------------------------------------+" +echo "| BUILD STD LIBRARY |" +echo "+--------------------------------------+" + +cd lib || exit 1 +make -B +if [ ! $? -eq 0 ]; then + echo "===> failed to build standard library" + exit 1 +fi + +echo "+--------------------------------------+" +echo "| successfully build standard library |" +echo "+--------------------------------------+"