Compare commits
30 Commits
prerelease
...
357c8745a4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
357c8745a4 | ||
|
|
4101144e26 | ||
|
|
6a32c4721c | ||
|
|
6de89ebb2f | ||
|
|
4d4749c65e | ||
|
|
916d94b32b | ||
| e3108b2606 | |||
| f3912ae49f | |||
|
|
9de85f3b72 | ||
|
|
41a6fb17da | ||
|
|
7a48771976 | ||
|
|
89abf4e036 | ||
|
|
df409dd3f6 | ||
|
|
646938ea79 | ||
|
|
9befc3760a | ||
|
|
3d2ba09518 | ||
| 94b86fc416 | |||
|
|
0a2aa7369f | ||
|
|
0b594d7882 | ||
|
|
c0ba18c37e | ||
|
|
608fd86003 | ||
|
|
434b0ed99e | ||
|
|
bfaf8df0d0 | ||
|
|
3e3df5595e | ||
|
|
51c6bdcea9 | ||
|
|
dd3b3b936d | ||
|
|
b6714b390a | ||
|
|
a9b1d23f79 | ||
|
|
6d3e79b731 | ||
|
|
b3ee64d294 |
68
Jenkinsfile
vendored
Normal file
68
Jenkinsfile
vendored
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
pipeline {
|
||||||
|
agent any
|
||||||
|
stages {
|
||||||
|
stage('Checkout') {
|
||||||
|
steps {
|
||||||
|
checkout scm
|
||||||
|
sh 'git submodule update --init --recursive'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Setup Conan') {
|
||||||
|
steps {
|
||||||
|
sh '''
|
||||||
|
python3 -m venv /tmp/venv
|
||||||
|
. /tmp/venv/bin/activate
|
||||||
|
apt update
|
||||||
|
apt upgrade
|
||||||
|
apt install -y cmake flex python3 python3-pip python3-venv
|
||||||
|
pip install --upgrade pip
|
||||||
|
pip install conan
|
||||||
|
'''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Setup Conan Profile') {
|
||||||
|
steps {
|
||||||
|
sh '''
|
||||||
|
. /tmp/venv/bin/activate
|
||||||
|
if [ ! -f ~/.conan2/profiles/default ]; then
|
||||||
|
conan profile detect
|
||||||
|
fi
|
||||||
|
'''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Install Dependencies') {
|
||||||
|
steps {
|
||||||
|
sh '''
|
||||||
|
. /tmp/venv/bin/activate
|
||||||
|
conan install . --build=missing
|
||||||
|
'''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Build Project') {
|
||||||
|
steps {
|
||||||
|
sh '''
|
||||||
|
. /tmp/venv/bin/activate
|
||||||
|
conan build .
|
||||||
|
'''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Archive Build Artifacts') {
|
||||||
|
steps {
|
||||||
|
sh '''
|
||||||
|
# Copy LICENSE.txt into build/bin
|
||||||
|
cp LICENSE.txt build/bin/
|
||||||
|
|
||||||
|
# Create tarball with the contents of build/bin at the root
|
||||||
|
tar -czf chloride.tar.gz -C build/bin .
|
||||||
|
'''
|
||||||
|
// Archive the tarball
|
||||||
|
archiveArtifacts artifacts: 'chloride.tar.gz', allowEmptyArchive: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
77
README.md
77
README.md
@@ -4,6 +4,79 @@ SPDX-FileCopyrightText: 2025 William Bell
|
|||||||
SPDX-License-Identifier: GPL-3.0-or-later
|
SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
-->
|
-->
|
||||||
|
|
||||||
# Chloride
|
<div align="center">
|
||||||
|
<p>
|
||||||
|
<img width="150" src="logo/logo.png">
|
||||||
|
</p>
|
||||||
|
<h1>Chloride</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
An Argon interpreter written in C
|
Chloride is the new C-based interpreter for the Argon programming language.
|
||||||
|
It is designed as a drop-in replacement for the older Go implementation (argon-v3), while introducing a more efficient runtime and a cleaner, more consistent object model.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
Currently, builds are only being made for linux x86_64 at [the projects Jenklins instance](https://jenkins.wbell.dev/job/chloride/).
|
||||||
|
|
||||||
|
If this does not satify your requirements, feel free to build for your platform. the dependancies are `conan`, `flex`, `cmake` and `gcc`.
|
||||||
|
|
||||||
|
install using conan.
|
||||||
|
```
|
||||||
|
conan install . --build=missing
|
||||||
|
```
|
||||||
|
|
||||||
|
and finally build using conan.
|
||||||
|
```
|
||||||
|
conan build .
|
||||||
|
```
|
||||||
|
|
||||||
|
the final build can be found in `build/bin`.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Chloride aims to remain as interchangeable with argon-v3 as possible.
|
||||||
|
Most existing Argon code should run with minimal or no changes, and backwards compatibility is an ongoing priority.
|
||||||
|
Where behaviour differs, the goal is for those differences to be predictable and well-defined rather than accidental quirks.
|
||||||
|
|
||||||
|
This interpreter replaces argon-v3's AST-walking runtime with a proper bytecode compiler, caching system, and virtual machine.
|
||||||
|
The result is a more consistent execution model, lower memory usage, and improved overall performance, even though speed is not the sole focus of the project.
|
||||||
|
|
||||||
|
## Key Improvements Over argon-v3
|
||||||
|
|
||||||
|
- **Bytecode + VM architecture**
|
||||||
|
Chloride compiles source code into bytecode and executes it through a dedicated virtual machine.
|
||||||
|
The previous interpreter evaluated the AST directly at runtime, which limited performance and made optimisations difficult.
|
||||||
|
|
||||||
|
- **Reduced memory usage and CPU overhead**
|
||||||
|
Chloride is written in C with an emphasis on minimal allocations, predictable lifetimes, and efficient object handling.
|
||||||
|
|
||||||
|
- **Unified object model**
|
||||||
|
In contrast to argon-v3, where some values (such as numbers) were not objects, Chloride treats every value as a first-class object.
|
||||||
|
This simplifies the runtime and ensures a more consistent behaviour across all types.
|
||||||
|
|
||||||
|
- **Proper class and inheritance system**
|
||||||
|
Classes in Chloride are real objects, supporting inheritance and introspection in a clean, well-defined manner.
|
||||||
|
The old interpreter treated classes as a special-case construct, which restricted the language's expressiveness.
|
||||||
|
|
||||||
|
- **Backwards compatibility focus**
|
||||||
|
Chloride aims to match argon-v3’s behaviour closely enough that most existing Argon programs run unchanged.
|
||||||
|
Compatibility fixes and behavioural parity are treated as long-term goals.
|
||||||
|
|
||||||
|
## Project Goals
|
||||||
|
|
||||||
|
- Maintain high compatibility with argon-v3.
|
||||||
|
- Minimise memory usage and improve runtime efficiency.
|
||||||
|
- Provide a stable, maintainable interpreter core.
|
||||||
|
- Keep the implementation straightforward so that future language features can be built cleanly on top of it.
|
||||||
|
- Serve as the reference interpreter for Argon going forward.
|
||||||
|
|
||||||
|
|
||||||
|
## Project Status
|
||||||
|
|
||||||
|
Chloride is still under active development.
|
||||||
|
The object model is largely complete, but several core language features are missing or experimental. Basic control flow constructs such as for loops are not implemented yet, partly because the older syntax was confusing and may be replaced with something clearer. While backwards compatibility is a goal, perfect compatibility is unlikely, especially where new syntax or improved semantics resolve long-standing issues in argon-v3.
|
||||||
|
|
||||||
|
The interpreter currently contains known performance issues and occasional segmentation faults, and part of the development process is identifying and removing these. The intention is to stabilise the runtime, finalise the syntax, and avoid any further major redesigns. The hope is that Chloride becomes both the long-term Argon interpreter and the last large rewrite the language needs.
|
||||||
|
|
||||||
|
# Licence
|
||||||
|
GNU General Public License v3.0
|
||||||
|
|||||||
@@ -16,12 +16,15 @@ class ArgonConan(ConanFile):
|
|||||||
# Remove tool_requires, no flex from Conan
|
# Remove tool_requires, no flex from Conan
|
||||||
requires = [
|
requires = [
|
||||||
"gmp/6.3.0",
|
"gmp/6.3.0",
|
||||||
"bdwgc/8.2.8"
|
"bdwgc/8.2.6"
|
||||||
]
|
]
|
||||||
|
|
||||||
default_options = {
|
default_options = {
|
||||||
"gmp/*:shared": False,
|
"gmp/*:shared": False,
|
||||||
"bdwgc/*:shared": False
|
"bdwgc/*:shared": False,
|
||||||
|
"bdwgc/*:parallel_mark": False,
|
||||||
|
"bdwgc/*:threads": True,
|
||||||
|
"bdwgc/*:disable_debug": True,
|
||||||
}
|
}
|
||||||
|
|
||||||
def layout(self):
|
def layout(self):
|
||||||
|
|||||||
BIN
logo/logo.png
Normal file
BIN
logo/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
84
logo/logo.svg
Normal file
84
logo/logo.svg
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="512"
|
||||||
|
height="512"
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||||
|
sodipodi:docname="logo.svg"
|
||||||
|
inkscape:export-filename="logo.png"
|
||||||
|
inkscape:export-xdpi="96"
|
||||||
|
inkscape:export-ydpi="96"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview1"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:zoom="1.6199927"
|
||||||
|
inkscape:cx="166.66742"
|
||||||
|
inkscape:cy="208.33427"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1414"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1" />
|
||||||
|
<defs
|
||||||
|
id="defs1">
|
||||||
|
<rect
|
||||||
|
x="96.463768"
|
||||||
|
y="150.58824"
|
||||||
|
width="287.20887"
|
||||||
|
height="242.68713"
|
||||||
|
id="rect1" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<path
|
||||||
|
sodipodi:type="star"
|
||||||
|
style="fill:#555555;fill-opacity:1"
|
||||||
|
id="path7"
|
||||||
|
inkscape:flatsided="false"
|
||||||
|
sodipodi:sides="17"
|
||||||
|
sodipodi:cx="150.15175"
|
||||||
|
sodipodi:cy="58.052856"
|
||||||
|
sodipodi:r1="46.661324"
|
||||||
|
sodipodi:r2="37.32906"
|
||||||
|
sodipodi:arg1="0.30400094"
|
||||||
|
sodipodi:arg2="0.48880051"
|
||||||
|
inkscape:rounded="0.4"
|
||||||
|
inkscape:randomized="2.7755576e-17"
|
||||||
|
d="m 194.67349,72.020461 c -1.44879,4.618019 -9.29136,-0.712277 -11.56404,3.560897 -2.27268,4.273175 6.53108,7.796197 3.5119,11.579008 -3.01918,3.782812 -8.40662,-4.020601 -12.06948,-0.856972 -3.66286,3.163629 3.27373,9.629034 -0.90807,12.065747 -4.18181,2.436719 -6.38654,-6.785922 -10.94489,-5.159103 -4.55835,1.626819 -0.42574,10.161412 -5.2054,10.922942 -4.77966,0.76152 -3.50391,-8.634768 -8.34212,-8.76447 -4.83821,-0.129703 -4.06772,9.32144 -8.79971,8.30493 -4.732,-1.01651 -0.14806,-9.317437 -4.61271,-11.186144 -4.46464,-1.868708 -7.16032,7.222558 -11.20557,4.565293 -4.04525,-2.657264 3.22778,-8.741737 -0.26032,-12.097069 -3.4881,-3.355333 -9.28589,4.148226 -12.09806,0.209088 -2.81217,-3.939138 6.1677,-6.985416 4.12723,-11.374218 -2.04047,-4.388801 -10.15735,0.513654 -11.35664,-4.175355 -1.19929,-4.689009 8.27463,-4.285677 7.95737,-9.115215 -0.31727,-4.829539 -9.65701,-3.190291 -9.08144,-7.995895 0.57556,-4.805603 9.26403,-1.007133 10.71282,-5.625152 1.44879,-4.61802 -7.85242,-6.463369 -5.57974,-10.736544 2.27268,-4.273174 9.00227,2.407431 12.02145,-1.375381 3.01917,-3.782811 -4.98733,-8.863533 -1.32447,-12.027163 3.66286,-3.163629 7.5247,5.496857 11.70651,3.060143 4.18181,-2.436714 -1.44866,-10.066629 3.10969,-11.693447 4.55835,-1.626819 5.03088,7.843901 9.81054,7.082377 4.77966,-0.761525 2.28565,-9.91017 7.12386,-9.780467 4.83821,0.129703 1.85761,9.131584 6.58961,10.148098 4.73199,1.016513 5.71126,-8.415288 10.17591,-6.546581 4.46464,1.868707 -1.56654,9.185997 2.47871,11.843261 4.04525,2.657265 8.36555,-5.783874 11.85365,-2.428541 3.4881,3.355332 -4.77911,7.999788 -1.96695,11.938927 2.81217,3.939138 9.89002,-2.371317 11.93049,2.017485 2.04047,4.388801 -7.34625,5.733164 -6.14696,10.422174 1.19929,4.689009 10.07879,1.3615 10.39605,6.191039 0.31727,4.829538 -8.92123,2.692245 -9.49679,7.497849 -0.57556,4.805603 8.90636,4.910439 7.45757,9.528459 z"
|
||||||
|
inkscape:transform-center-x="1.5847721"
|
||||||
|
inkscape:transform-center-y="-0.51694771"
|
||||||
|
transform="matrix(5.4829104,-0.55336355,0.55336355,5.4829104,-597.77534,21.197933)" />
|
||||||
|
<path
|
||||||
|
style="font-weight:bold;font-size:96px;font-family:'TeX Gyre Heros';-inkscape-font-specification:'TeX Gyre Heros, Bold';white-space:pre;inline-size:117.996;fill:#a9bacd"
|
||||||
|
d="m 231.18969,194.33982 h -14.016 c -0.864,8.928 -6.528,12.96 -15.456,12.96 -11.136,0 -17.664,-8.544 -17.664,-23.808 0,-15.456 6.816,-24.096 18.144,-24.096 7.776,0 12.864,3.552 14.976,12.576 h 13.728 c -1.248,-16.128 -13.44,-24.864 -29.184,-24.864 -19.776,0 -32.064,13.536 -32.064,36.192 0,22.464 12.192,36.096 31.68,36.096 17.376,0 28.992,-9.024 29.856,-25.056 z m 23.42401,23.904 v -69.984 h -13.44 v 69.984 z"
|
||||||
|
id="text2"
|
||||||
|
transform="matrix(4.4012947,0,0,3.7064713,-720.43857,-423.2176)"
|
||||||
|
aria-label="Cl" />
|
||||||
|
<rect
|
||||||
|
style="fill:#a9bacd;fill-opacity:1;stroke-width:0.783784"
|
||||||
|
id="rect4"
|
||||||
|
width="43.448219"
|
||||||
|
height="12.658142"
|
||||||
|
x="421.52911"
|
||||||
|
y="134.00171"
|
||||||
|
sodipodi:insensitive="true" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.8 KiB |
@@ -16,11 +16,11 @@ typedef enum {
|
|||||||
__base__,
|
__base__,
|
||||||
__class__,
|
__class__,
|
||||||
__name__,
|
__name__,
|
||||||
__binding__,
|
|
||||||
__function__,
|
|
||||||
|
|
||||||
BUILT_IN_ARRAY_COUNT,
|
BUILT_IN_ARRAY_COUNT,
|
||||||
|
|
||||||
|
__binding__,
|
||||||
|
__function__,
|
||||||
__add__,
|
__add__,
|
||||||
__string__,
|
__string__,
|
||||||
__subtract__,
|
__subtract__,
|
||||||
@@ -29,13 +29,15 @@ typedef enum {
|
|||||||
__new__,
|
__new__,
|
||||||
__init__,
|
__init__,
|
||||||
__boolean__,
|
__boolean__,
|
||||||
__get_attr__,
|
__getattr__,
|
||||||
field__address,
|
field__address,
|
||||||
__call__,
|
__call__,
|
||||||
__number__,
|
__number__,
|
||||||
field_length,
|
field_length,
|
||||||
__getattribute__,
|
__getattribute__,
|
||||||
__set_attr__,
|
__setattr__,
|
||||||
|
__getitem__,
|
||||||
|
__setitem__,
|
||||||
__hash__,
|
__hash__,
|
||||||
__repr__,
|
__repr__,
|
||||||
|
|
||||||
|
|||||||
29
src/import.c
29
src/import.c
@@ -43,6 +43,15 @@ static inline uint64_t htole64(uint64_t x) { return x; }
|
|||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int is_regular_file(const char *path) {
|
||||||
|
struct stat path_stat;
|
||||||
|
stat(path, &path_stat);
|
||||||
|
return S_ISREG(path_stat.st_mode);
|
||||||
|
}
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
#include <libkern/OSByteOrder.h>
|
#include <libkern/OSByteOrder.h>
|
||||||
#define htole32(x) OSSwapHostToLittleInt32(x)
|
#define htole32(x) OSSwapHostToLittleInt32(x)
|
||||||
@@ -285,7 +294,6 @@ Translated load_argon_file(char *path, ArErr *err) {
|
|||||||
sizeof(cache_file_path));
|
sizeof(cache_file_path));
|
||||||
cwk_path_change_extension(cache_file_path, BYTECODE_EXTENTION,
|
cwk_path_change_extension(cache_file_path, BYTECODE_EXTENTION,
|
||||||
cache_file_path, sizeof(cache_file_path));
|
cache_file_path, sizeof(cache_file_path));
|
||||||
|
|
||||||
FILE *file = fopen(path, "r");
|
FILE *file = fopen(path, "r");
|
||||||
if (!file) {
|
if (!file) {
|
||||||
*err = create_err(0, 0, 0, NULL, "File Error", "Unable to open file '%s'",
|
*err = create_err(0, 0, 0, NULL, "File Error", "Unable to open file '%s'",
|
||||||
@@ -400,7 +408,8 @@ Translated load_argon_file(char *path, ArErr *err) {
|
|||||||
Translated gc_translated = {
|
Translated gc_translated = {
|
||||||
translated.registerCount, translated.registerAssignment, NULL, {}, {},
|
translated.registerCount, translated.registerAssignment, NULL, {}, {},
|
||||||
translated.path};
|
translated.path};
|
||||||
gc_translated.bytecode.data = ar_alloc_atomic(translated.bytecode.capacity);
|
gc_translated.bytecode.data = ar_alloc_atomic(translated.bytecode.capacity +
|
||||||
|
translated.constants.capacity);
|
||||||
memcpy(gc_translated.bytecode.data, translated.bytecode.data,
|
memcpy(gc_translated.bytecode.data, translated.bytecode.data,
|
||||||
translated.bytecode.capacity);
|
translated.bytecode.capacity);
|
||||||
gc_translated.bytecode.element_size = translated.bytecode.element_size;
|
gc_translated.bytecode.element_size = translated.bytecode.element_size;
|
||||||
@@ -408,7 +417,8 @@ Translated load_argon_file(char *path, ArErr *err) {
|
|||||||
gc_translated.bytecode.resizable = false;
|
gc_translated.bytecode.resizable = false;
|
||||||
gc_translated.bytecode.capacity =
|
gc_translated.bytecode.capacity =
|
||||||
translated.bytecode.size * translated.bytecode.element_size;
|
translated.bytecode.size * translated.bytecode.element_size;
|
||||||
gc_translated.constants.data = ar_alloc_atomic(translated.constants.capacity);
|
gc_translated.constants.data =
|
||||||
|
gc_translated.bytecode.data + translated.bytecode.capacity;
|
||||||
memcpy(gc_translated.constants.data, translated.constants.data,
|
memcpy(gc_translated.constants.data, translated.constants.data,
|
||||||
translated.constants.capacity);
|
translated.constants.capacity);
|
||||||
gc_translated.constants.size = translated.constants.size;
|
gc_translated.constants.size = translated.constants.size;
|
||||||
@@ -422,8 +432,8 @@ Translated load_argon_file(char *path, ArErr *err) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char *PRE_PATHS_TO_TEST[] = {"", "", "argon_modules", "argon_modules"};
|
const char *PRE_PATHS_TO_TEST[] = {"", "", "argon_modules", "argon_modules"};
|
||||||
const char *POST_PATHS_TO_TEST[sizeof(PRE_PATHS_TO_TEST)/sizeof(char *)] = {"", "init.ar", "",
|
const char *POST_PATHS_TO_TEST[sizeof(PRE_PATHS_TO_TEST) / sizeof(char *)] = {
|
||||||
"init.ar"};
|
"", "init.ar", "", "init.ar"};
|
||||||
|
|
||||||
struct hashmap *importing_hash_table = NULL;
|
struct hashmap *importing_hash_table = NULL;
|
||||||
struct hashmap_GC *imported_hash_table = NULL;
|
struct hashmap_GC *imported_hash_table = NULL;
|
||||||
@@ -432,7 +442,8 @@ Stack *ar_import(char *current_directory, char *path_relative, ArErr *err) {
|
|||||||
char path[FILENAME_MAX];
|
char path[FILENAME_MAX];
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (size_t i = 0; i < sizeof(PRE_PATHS_TO_TEST) / sizeof(char *); i++) {
|
for (size_t i = 0; i < sizeof(PRE_PATHS_TO_TEST) / sizeof(char *); i++) {
|
||||||
cwk_path_get_absolute(current_directory, PRE_PATHS_TO_TEST[i], path, sizeof(path));
|
cwk_path_get_absolute(current_directory, PRE_PATHS_TO_TEST[i], path,
|
||||||
|
sizeof(path));
|
||||||
cwk_path_get_absolute(path, path_relative, path, sizeof(path));
|
cwk_path_get_absolute(path, path_relative, path, sizeof(path));
|
||||||
cwk_path_get_absolute(path, POST_PATHS_TO_TEST[i], path, sizeof(path));
|
cwk_path_get_absolute(path, POST_PATHS_TO_TEST[i], path, sizeof(path));
|
||||||
if (file_exists(path)) {
|
if (file_exists(path)) {
|
||||||
@@ -445,7 +456,8 @@ Stack *ar_import(char *current_directory, char *path_relative, ArErr *err) {
|
|||||||
path_relative);
|
path_relative);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!importing_hash_table) importing_hash_table = createHashmap();
|
if (!importing_hash_table)
|
||||||
|
importing_hash_table = createHashmap();
|
||||||
uint64_t hash = siphash64_bytes(path, strlen(path), siphash_key);
|
uint64_t hash = siphash64_bytes(path, strlen(path), siphash_key);
|
||||||
hashmap_insert(importing_hash_table, hash, path, (void *)true, 0);
|
hashmap_insert(importing_hash_table, hash, path, (void *)true, 0);
|
||||||
Translated translated = load_argon_file(path, err);
|
Translated translated = load_argon_file(path, err);
|
||||||
@@ -463,7 +475,8 @@ Stack *ar_import(char *current_directory, char *path_relative, ArErr *err) {
|
|||||||
double time_spent = (double)(end - start) / CLOCKS_PER_SEC;
|
double time_spent = (double)(end - start) / CLOCKS_PER_SEC;
|
||||||
fprintf(stderr, "Execution time taken: %f seconds\n", time_spent);
|
fprintf(stderr, "Execution time taken: %f seconds\n", time_spent);
|
||||||
hashmap_insert(importing_hash_table, hash, path, (void *)false, 0);
|
hashmap_insert(importing_hash_table, hash, path, (void *)false, 0);
|
||||||
if (!imported_hash_table) imported_hash_table = createHashmap_GC();
|
if (!imported_hash_table)
|
||||||
|
imported_hash_table = createHashmap_GC();
|
||||||
hashmap_insert_GC(imported_hash_table, hash, path, main_scope, 0);
|
hashmap_insert_GC(imported_hash_table, hash, path, main_scope, 0);
|
||||||
return main_scope;
|
return main_scope;
|
||||||
}
|
}
|
||||||
33
src/memory.c
33
src/memory.c
@@ -6,12 +6,11 @@
|
|||||||
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include <gc.h>
|
#include <gc.h>
|
||||||
#include <gc/gc.h>
|
#include <pthread.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h> // for malloc/free (temp arena fallback)
|
#include <stdlib.h> // for malloc/free (temp arena fallback)
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
void *checked_malloc(size_t size) {
|
void *checked_malloc(size_t size) {
|
||||||
void *ptr = malloc(size);
|
void *ptr = malloc(size);
|
||||||
@@ -22,6 +21,15 @@ void *checked_malloc(size_t size) {
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *checked_realloc(void *ptr, size_t size) {
|
||||||
|
void *new_ptr = realloc(ptr, size);
|
||||||
|
if (!new_ptr) {
|
||||||
|
fprintf(stderr, "fatal error: failed to allocate %zu bytes\n", size);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
return new_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
struct allocation *memory_allocations = NULL;
|
struct allocation *memory_allocations = NULL;
|
||||||
size_t memory_allocations_size = 0;
|
size_t memory_allocations_size = 0;
|
||||||
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
@@ -29,7 +37,8 @@ pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
|||||||
void ar_memory_init() {
|
void ar_memory_init() {
|
||||||
GC_INIT();
|
GC_INIT();
|
||||||
// memory_allocations_size = 8;
|
// memory_allocations_size = 8;
|
||||||
// memory_allocations = malloc(memory_allocations_size*sizeof(struct allocation));
|
// memory_allocations = malloc(memory_allocations_size*sizeof(struct
|
||||||
|
// allocation));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ar_memory_shutdown() {
|
void ar_memory_shutdown() {
|
||||||
@@ -41,9 +50,23 @@ void ar_memory_shutdown() {
|
|||||||
// free(memory_allocations);
|
// free(memory_allocations);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ar_alloc(size_t size) { return GC_MALLOC(size); }
|
void *ar_alloc(size_t size) {
|
||||||
|
void *ptr = GC_MALLOC(size);
|
||||||
|
if (!ptr) {
|
||||||
|
fprintf(stderr, "panic: unable to allocate memory\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
void *ar_realloc(void *old, size_t size) { return GC_REALLOC(old, size); }
|
void *ar_realloc(void *old, size_t size) {
|
||||||
|
void *ptr = GC_REALLOC(old, size);
|
||||||
|
if (!ptr) {
|
||||||
|
fprintf(stderr, "panic: unable to allocate memory\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
void ar_finalizer(void *obj, GC_finalization_proc fn, void *client_data,
|
void ar_finalizer(void *obj, GC_finalization_proc fn, void *client_data,
|
||||||
GC_finalization_proc *old_fn, void **old_client_data) {
|
GC_finalization_proc *old_fn, void **old_client_data) {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#include <stddef.h> // for size_t
|
#include <stddef.h> // for size_t
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <gc/gc.h>
|
#include <gc.h>
|
||||||
|
|
||||||
// GC-managed allocations
|
// GC-managed allocations
|
||||||
|
|
||||||
@@ -37,5 +37,6 @@ void ar_memory_init();
|
|||||||
void ar_memory_shutdown();
|
void ar_memory_shutdown();
|
||||||
|
|
||||||
void *checked_malloc(size_t size);
|
void *checked_malloc(size_t size);
|
||||||
|
void *checked_realloc(void *ptr, size_t size);
|
||||||
|
|
||||||
#endif // ARGON_MEMORY_H
|
#endif // ARGON_MEMORY_H
|
||||||
@@ -15,15 +15,13 @@
|
|||||||
|
|
||||||
ParsedValueReturn parse_access(char *file, DArray *tokens, size_t *index,
|
ParsedValueReturn parse_access(char *file, DArray *tokens, size_t *index,
|
||||||
ParsedValue *to_access) {
|
ParsedValue *to_access) {
|
||||||
Token *first_token = darray_get(tokens, *index);
|
|
||||||
(*index)++;
|
|
||||||
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));
|
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));
|
||||||
if (first_token->type == TOKEN_DOT) {
|
|
||||||
ParsedAccess *parsedAccess = checked_malloc(sizeof(ParsedAccess));
|
ParsedAccess *parsedAccess = checked_malloc(sizeof(ParsedAccess));
|
||||||
parsedAccess->to_access = to_access;
|
parsedAccess->to_access = to_access;
|
||||||
parsedAccess->access = NULL;
|
parsedAccess->access = NULL;
|
||||||
parsedValue->type = AST_ACCESS;
|
parsedValue->type = AST_ACCESS;
|
||||||
parsedValue->data = parsedAccess;
|
parsedValue->data = parsedAccess;
|
||||||
|
(*index)++;
|
||||||
ArErr err = error_if_finished(file, tokens, index);
|
ArErr err = error_if_finished(file, tokens, index);
|
||||||
if (err.exists) {
|
if (err.exists) {
|
||||||
free_parsed(parsedValue);
|
free_parsed(parsedValue);
|
||||||
@@ -49,7 +47,6 @@ ParsedValueReturn parse_access(char *file, DArray *tokens, size_t *index,
|
|||||||
return parsedString;
|
return parsedString;
|
||||||
}
|
}
|
||||||
parsedAccess->access = parsedString.value;
|
parsedAccess->access = parsedString.value;
|
||||||
}
|
|
||||||
(*index)++;
|
(*index)++;
|
||||||
return (ParsedValueReturn){no_err, parsedValue};
|
return (ParsedValueReturn){no_err, parsedValue};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,12 +84,22 @@ ParsedValueReturn parse_assign(char *file, DArray *tokens,
|
|||||||
return (ParsedValueReturn){err, NULL};
|
return (ParsedValueReturn){err, NULL};
|
||||||
}
|
}
|
||||||
(*index)++;
|
(*index)++;
|
||||||
|
ArErr err = error_if_finished(file, tokens, index);
|
||||||
|
if (err.exists) {
|
||||||
|
free_parsed(assign_to);
|
||||||
|
free(assign_to);
|
||||||
|
return (ParsedValueReturn){err, NULL};
|
||||||
|
}
|
||||||
token = darray_get(tokens, *index);
|
token = darray_get(tokens, *index);
|
||||||
ParsedValueReturn from = parse_token(file, tokens, index, true);
|
ParsedValueReturn from = parse_token(file, tokens, index, true);
|
||||||
if (from.err.exists) {
|
if (from.err.exists) {
|
||||||
|
free_parsed(assign_to);
|
||||||
|
free(assign_to);
|
||||||
return from;
|
return from;
|
||||||
}
|
}
|
||||||
if (!from.value) {
|
if (!from.value) {
|
||||||
|
free_parsed(assign_to);
|
||||||
|
free(assign_to);
|
||||||
return (ParsedValueReturn){create_err(token->line, token->column,
|
return (ParsedValueReturn){create_err(token->line, token->column,
|
||||||
token->length, file, "Syntax Error",
|
token->length, file, "Syntax Error",
|
||||||
"expected body"),
|
"expected body"),
|
||||||
@@ -110,12 +120,6 @@ ParsedValueReturn parse_assign(char *file, DArray *tokens,
|
|||||||
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));
|
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));
|
||||||
parsedValue->type = AST_ASSIGN;
|
parsedValue->type = AST_ASSIGN;
|
||||||
parsedValue->data = assign;
|
parsedValue->data = assign;
|
||||||
ArErr err = error_if_finished(file, tokens, index);
|
|
||||||
if (err.exists) {
|
|
||||||
free_parsed(parsedValue);
|
|
||||||
free(parsedValue);
|
|
||||||
return (ParsedValueReturn){err, NULL};
|
|
||||||
}
|
|
||||||
assign->from = from.value;
|
assign->from = from.value;
|
||||||
return (ParsedValueReturn){no_err, parsedValue};
|
return (ParsedValueReturn){no_err, parsedValue};
|
||||||
}
|
}
|
||||||
|
|||||||
80
src/parser/assignable/item/item.c
Normal file
80
src/parser/assignable/item/item.c
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 William Bell
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "item.h"
|
||||||
|
#include "../../../lexer/token.h"
|
||||||
|
#include "../../../memory.h"
|
||||||
|
#include "../../parser.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
ParsedValueReturn parse_item_access(char *file, DArray *tokens, size_t *index,
|
||||||
|
ParsedValue *to_access) {
|
||||||
|
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));
|
||||||
|
ParsedItemAccess *parsedItemAccess = checked_malloc(sizeof(ParsedItemAccess));
|
||||||
|
parsedItemAccess->to_access = to_access;
|
||||||
|
size_t capacity = 4;
|
||||||
|
parsedItemAccess->items = checked_malloc(capacity * sizeof(ParsedValue *));
|
||||||
|
parsedItemAccess->itemc = 0;
|
||||||
|
parsedValue->type = AST_ITEM_ACCESS;
|
||||||
|
parsedValue->data = parsedItemAccess;
|
||||||
|
Token *token = darray_get(tokens, *index);
|
||||||
|
parsedItemAccess->line = token->line;
|
||||||
|
parsedItemAccess->column = token->column;
|
||||||
|
parsedItemAccess->length = token->length;
|
||||||
|
(*index)++;
|
||||||
|
while (true) {
|
||||||
|
ArErr err = error_if_finished(file, tokens, index);
|
||||||
|
if (err.exists) {
|
||||||
|
free_parsed(parsedValue);
|
||||||
|
free(parsedValue);
|
||||||
|
return (ParsedValueReturn){err, NULL};
|
||||||
|
}
|
||||||
|
ParsedValueReturn parsedKey = parse_token(file, tokens, index, true);
|
||||||
|
if (parsedKey.err.exists) {
|
||||||
|
free_parsed(parsedValue);
|
||||||
|
free(parsedValue);
|
||||||
|
return parsedKey;
|
||||||
|
}
|
||||||
|
parsedItemAccess->items[parsedItemAccess->itemc++] = parsedKey.value;
|
||||||
|
if (parsedItemAccess->itemc > capacity) {
|
||||||
|
capacity *= 2;
|
||||||
|
parsedItemAccess->items = checked_realloc(
|
||||||
|
parsedItemAccess->items, capacity * sizeof(ParsedValue *));
|
||||||
|
}
|
||||||
|
Token *token = darray_get(tokens, *index);
|
||||||
|
(*index)++;
|
||||||
|
if (token->type == TOKEN_COMMA) {
|
||||||
|
continue;
|
||||||
|
} else if (token->type == TOKEN_RBRACKET) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
free_parsed(parsedValue);
|
||||||
|
free(parsedValue);
|
||||||
|
return (ParsedValueReturn){
|
||||||
|
create_err(token->line, token->column, token->length, file,
|
||||||
|
"Syntax Error",
|
||||||
|
"expected either a comma or a closing bracket"),
|
||||||
|
NULL};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (ParsedValueReturn){no_err, parsedValue};
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_parse_item_access(void *ptr) {
|
||||||
|
ParsedValue *parsedValue = ptr;
|
||||||
|
ParsedItemAccess *parsedItemAccess = parsedValue->data;
|
||||||
|
free_parsed(parsedItemAccess->to_access);
|
||||||
|
free(parsedItemAccess->to_access);
|
||||||
|
for (size_t i = 0; i < parsedItemAccess->itemc; i++) {
|
||||||
|
free_parsed(parsedItemAccess->items[i]);
|
||||||
|
free(parsedItemAccess->items[i]);
|
||||||
|
}
|
||||||
|
free(parsedItemAccess->items);
|
||||||
|
free(parsedItemAccess);
|
||||||
|
}
|
||||||
25
src/parser/assignable/item/item.h
Normal file
25
src/parser/assignable/item/item.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 William Bell
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ITEM_ACCESS_H
|
||||||
|
#define ITEM_ACCESS_H
|
||||||
|
#include "../../parser.h"
|
||||||
|
#include "../../../lexer/token.h" // for Token
|
||||||
|
typedef struct {
|
||||||
|
ParsedValue *to_access;
|
||||||
|
ParsedValue **items;
|
||||||
|
size_t itemc;
|
||||||
|
size_t line;
|
||||||
|
size_t column;
|
||||||
|
size_t length;
|
||||||
|
} ParsedItemAccess;
|
||||||
|
|
||||||
|
ParsedValueReturn parse_item_access(char *file, DArray *tokens, size_t *index,
|
||||||
|
ParsedValue *to_access);
|
||||||
|
|
||||||
|
void free_parse_item_access(void *ptr);
|
||||||
|
|
||||||
|
#endif // ACCESS_H
|
||||||
@@ -47,6 +47,7 @@ ParsedValueReturn parse_parentheses(char *file, DArray *tokens, size_t *index) {
|
|||||||
"Syntax Error", "expected comma"),
|
"Syntax Error", "expected comma"),
|
||||||
NULL};
|
NULL};
|
||||||
}
|
}
|
||||||
|
(*index)++;
|
||||||
skip_newlines_and_indents(tokens, index);
|
skip_newlines_and_indents(tokens, index);
|
||||||
err = error_if_finished(file, tokens, index);
|
err = error_if_finished(file, tokens, index);
|
||||||
if (err.exists) {
|
if (err.exists) {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "assignable/assign/assign.h"
|
#include "assignable/assign/assign.h"
|
||||||
#include "assignable/call/call.h"
|
#include "assignable/call/call.h"
|
||||||
#include "assignable/identifier/identifier.h"
|
#include "assignable/identifier/identifier.h"
|
||||||
|
#include "assignable/item/item.h"
|
||||||
#include "declaration/declaration.h"
|
#include "declaration/declaration.h"
|
||||||
#include "dictionary/dictionary.h"
|
#include "dictionary/dictionary.h"
|
||||||
#include "dowrap/dowrap.h"
|
#include "dowrap/dowrap.h"
|
||||||
@@ -164,9 +165,11 @@ ParsedValueReturn parse_token_full(char *file, DArray *tokens, size_t *index,
|
|||||||
output = parse_call(file, tokens, index, output.value);
|
output = parse_call(file, tokens, index, output.value);
|
||||||
break;
|
break;
|
||||||
case TOKEN_DOT:
|
case TOKEN_DOT:
|
||||||
case TOKEN_LBRACKET:
|
|
||||||
output = parse_access(file, tokens, index, output.value);
|
output = parse_access(file, tokens, index, output.value);
|
||||||
break;
|
break;
|
||||||
|
case TOKEN_LBRACKET:
|
||||||
|
output = parse_item_access(file, tokens, index, output.value);
|
||||||
|
break;
|
||||||
SWITCH_OPERATIONS
|
SWITCH_OPERATIONS
|
||||||
if (process_operations) {
|
if (process_operations) {
|
||||||
output = parse_operations(file, tokens, index, output.value);
|
output = parse_operations(file, tokens, index, output.value);
|
||||||
@@ -199,7 +202,7 @@ ArErr parser(char *file, DArray *parsed, DArray *tokens, bool inline_flag) {
|
|||||||
if (expecting_new_line) {
|
if (expecting_new_line) {
|
||||||
Token *token = darray_get(tokens, old_index);
|
Token *token = darray_get(tokens, old_index);
|
||||||
return create_err(token->line, token->column, token->length, file,
|
return create_err(token->line, token->column, token->length, file,
|
||||||
"Syntax Error", "expected new line");
|
"Syntax Error", "invalid syntax");
|
||||||
}
|
}
|
||||||
expecting_new_line = true;
|
expecting_new_line = true;
|
||||||
darray_push(parsed, parsed_code.value);
|
darray_push(parsed, parsed_code.value);
|
||||||
@@ -241,6 +244,9 @@ void free_parsed(void *ptr) {
|
|||||||
case AST_ACCESS:
|
case AST_ACCESS:
|
||||||
free_parse_access(parsed);
|
free_parse_access(parsed);
|
||||||
break;
|
break;
|
||||||
|
case AST_ITEM_ACCESS:
|
||||||
|
free_parse_item_access(parsed);
|
||||||
|
break;
|
||||||
case AST_NULL:
|
case AST_NULL:
|
||||||
case AST_BOOLEAN:
|
case AST_BOOLEAN:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ typedef enum {
|
|||||||
AST_NUMBER,
|
AST_NUMBER,
|
||||||
AST_IF,
|
AST_IF,
|
||||||
AST_ACCESS,
|
AST_ACCESS,
|
||||||
|
AST_ITEM_ACCESS,
|
||||||
AST_CALL,
|
AST_CALL,
|
||||||
AST_DECLARATION,
|
AST_DECLARATION,
|
||||||
AST_NULL,
|
AST_NULL,
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -121,6 +122,7 @@ void run_call(ArgonObject *original_object, size_t argc, ArgonObject **argv,
|
|||||||
(int)object_name->value.as_str->length,
|
(int)object_name->value.as_str->length,
|
||||||
object_name->value.as_str->data,
|
object_name->value.as_str->data,
|
||||||
object->value.argon_fn->number_of_parameters, argc);
|
object->value.argon_fn->number_of_parameters, argc);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
Stack *scope = create_scope(object->value.argon_fn->stack, true);
|
Stack *scope = create_scope(object->value.argon_fn->stack, true);
|
||||||
for (size_t i = 0; i < argc; i++) {
|
for (size_t i = 0; i < argc; i++) {
|
||||||
@@ -131,6 +133,8 @@ void run_call(ArgonObject *original_object, size_t argc, ArgonObject **argv,
|
|||||||
new_string_object(key.data, key.length, 0, hash), value,
|
new_string_object(key.data, key.length, 0, hash), value,
|
||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
|
if (CStackFrame) {
|
||||||
|
ArgonObject * registers[MAX_REGISTERS]; // fixed on the stack for speed purposes
|
||||||
StackFrame new_stackFrame = {
|
StackFrame new_stackFrame = {
|
||||||
{object->value.argon_fn->translated.registerCount,
|
{object->value.argon_fn->translated.registerCount,
|
||||||
object->value.argon_fn->translated.registerAssignment,
|
object->value.argon_fn->translated.registerAssignment,
|
||||||
@@ -140,8 +144,7 @@ void run_call(ArgonObject *original_object, size_t argc, ArgonObject **argv,
|
|||||||
object->value.argon_fn->bytecode_length, false},
|
object->value.argon_fn->bytecode_length, false},
|
||||||
object->value.argon_fn->translated.constants,
|
object->value.argon_fn->translated.constants,
|
||||||
object->value.argon_fn->translated.path},
|
object->value.argon_fn->translated.path},
|
||||||
{ar_alloc(object->value.argon_fn->translated.registerCount *
|
{registers,
|
||||||
sizeof(ArgonObject *)),
|
|
||||||
0,
|
0,
|
||||||
object->value.argon_fn->translated.path,
|
object->value.argon_fn->translated.path,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -154,13 +157,34 @@ void run_call(ArgonObject *original_object, size_t argc, ArgonObject **argv,
|
|||||||
for (size_t i = 0; i < new_stackFrame.translated.registerCount; i++) {
|
for (size_t i = 0; i < new_stackFrame.translated.registerCount; i++) {
|
||||||
new_stackFrame.state.registers[i] = NULL;
|
new_stackFrame.state.registers[i] = NULL;
|
||||||
}
|
}
|
||||||
if (CStackFrame) {
|
|
||||||
runtime(new_stackFrame.translated, new_stackFrame.state,
|
runtime(new_stackFrame.translated, new_stackFrame.state,
|
||||||
new_stackFrame.stack, err);
|
new_stackFrame.stack, err);
|
||||||
state->registers[0] = new_stackFrame.state.registers[0];
|
state->registers[0] = new_stackFrame.state.registers[0];
|
||||||
} else {
|
} else {
|
||||||
StackFrame *currentStackFrame = ar_alloc(sizeof(StackFrame));
|
StackFrame *currentStackFrame = ar_alloc(sizeof(StackFrame)+object->value.argon_fn->translated.registerCount *
|
||||||
*currentStackFrame = new_stackFrame;
|
sizeof(ArgonObject *));
|
||||||
|
*currentStackFrame = (StackFrame){
|
||||||
|
{object->value.argon_fn->translated.registerCount,
|
||||||
|
object->value.argon_fn->translated.registerAssignment,
|
||||||
|
NULL,
|
||||||
|
{object->value.argon_fn->bytecode, sizeof(uint8_t),
|
||||||
|
object->value.argon_fn->bytecode_length,
|
||||||
|
object->value.argon_fn->bytecode_length, false},
|
||||||
|
object->value.argon_fn->translated.constants,
|
||||||
|
object->value.argon_fn->translated.path},
|
||||||
|
{(ArgonObject **)((char*)currentStackFrame+sizeof(StackFrame)),
|
||||||
|
0,
|
||||||
|
object->value.argon_fn->translated.path,
|
||||||
|
NULL,
|
||||||
|
state->currentStackFramePointer,
|
||||||
|
{},
|
||||||
|
{}},
|
||||||
|
scope,
|
||||||
|
*state->currentStackFramePointer,
|
||||||
|
(*state->currentStackFramePointer)->depth + 1};
|
||||||
|
for (size_t i = 0; i < (*currentStackFrame).translated.registerCount; i++) {
|
||||||
|
(*currentStackFrame).state.registers[i] = NULL;
|
||||||
|
}
|
||||||
*state->currentStackFramePointer = currentStackFrame;
|
*state->currentStackFramePointer = currentStackFrame;
|
||||||
if ((*state->currentStackFramePointer)->depth >= 10000) {
|
if ((*state->currentStackFramePointer)->depth >= 10000) {
|
||||||
double logval =
|
double logval =
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#include "darray_armem.h"
|
#include "darray_armem.h"
|
||||||
#include "../../../memory.h"
|
#include "../../../memory.h"
|
||||||
#include <gc/gc.h>
|
#include <gc.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
|
|
||||||
#include "../../../memory.h"
|
#include "../../../memory.h"
|
||||||
#include <gc/gc.h>
|
#include <gc.h>
|
||||||
|
#include <inttypes.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -25,28 +26,50 @@ struct hashmap_GC *createHashmap_GC() {
|
|||||||
t->inline_count = 0;
|
t->inline_count = 0;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
void hashmap_GC_to_array(struct hashmap_GC *t, struct node_GC**array,
|
|
||||||
|
static int compare_node_asc(const void *a, const void *b) {
|
||||||
|
const struct node_GC *na = *(const struct node_GC **)a;
|
||||||
|
const struct node_GC *nb = *(const struct node_GC **)b;
|
||||||
|
|
||||||
|
// Ascending order (smallest order first)
|
||||||
|
if (na->order < nb->order)
|
||||||
|
return -1;
|
||||||
|
if (na->order > nb->order)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct node_GC ** hashmap_GC_to_array(struct hashmap_GC *t,
|
||||||
size_t *array_length) {
|
size_t *array_length) {
|
||||||
size_t array_size = 8;
|
size_t array_size = 8;
|
||||||
*array_length = 0;
|
*array_length = 0;
|
||||||
*array = ar_alloc(array_size * sizeof(struct node_GC));
|
struct node_GC ** array = ar_alloc(array_size * sizeof(struct node_GC*));
|
||||||
|
|
||||||
for (size_t i = 0; i < t->inline_count; i++) {
|
for (size_t i = 0; i < t->inline_count; i++) {
|
||||||
if (*array_length >= array_size) {
|
if (*array_length >= array_size) {
|
||||||
array_size *= 2;
|
array_size *= 2;
|
||||||
*array=ar_realloc(*array, array_size * sizeof(struct node_GC));
|
array = ar_realloc(array, array_size * sizeof(struct node_GC*));
|
||||||
}
|
}
|
||||||
(*array)[(*array_length)++] = t->inline_values[i];
|
array[(*array_length)++] = &t->inline_values[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < t->size; i++) {
|
for (size_t i = 0; i < t->size; i++) {
|
||||||
if (!t->list[i]) continue;
|
struct node_GC *list = t->list[i];
|
||||||
|
struct node_GC *temp = list;
|
||||||
|
while (temp) {
|
||||||
if (*array_length >= array_size) {
|
if (*array_length >= array_size) {
|
||||||
array_size *= 2;
|
array_size *= 2;
|
||||||
*array=ar_realloc(*array, array_size * sizeof(struct node_GC));
|
array = ar_realloc(array, array_size * sizeof(struct node_GC*));
|
||||||
}
|
}
|
||||||
(*array)[(*array_length)++] = *t->list[i];
|
array[(*array_length)++] = temp;
|
||||||
|
temp = temp->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qsort(array, *array_length, sizeof(struct node_GC*), compare_node_asc);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
void clear_hashmap_GC(struct hashmap_GC *t) {
|
void clear_hashmap_GC(struct hashmap_GC *t) {
|
||||||
if (!t->count)
|
if (!t->count)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ struct hashmap_GC *createHashmap_GC();
|
|||||||
|
|
||||||
void clear_hashmap_GC(struct hashmap_GC *t);
|
void clear_hashmap_GC(struct hashmap_GC *t);
|
||||||
|
|
||||||
void hashmap_GC_to_array(struct hashmap_GC *t, struct node_GC**array,
|
struct node_GC ** hashmap_GC_to_array(struct hashmap_GC *t,
|
||||||
size_t *array_length);
|
size_t *array_length);
|
||||||
|
|
||||||
int hashCode_GC(struct hashmap_GC *t, uint64_t hash);
|
int hashCode_GC(struct hashmap_GC *t, uint64_t hash);
|
||||||
|
|||||||
@@ -45,18 +45,20 @@ ArgonObject *create_ARGON_DICTIONARY_TYPE___string__(size_t argc,
|
|||||||
ArgonObject *object = argv[0];
|
ArgonObject *object = argv[0];
|
||||||
size_t string_length = 0;
|
size_t string_length = 0;
|
||||||
char *string = NULL;
|
char *string = NULL;
|
||||||
struct node_GC *keys;
|
size_t nodes_length;
|
||||||
size_t keys_length;
|
struct node_GC ** nodes = hashmap_GC_to_array(object->value.as_hashmap, &nodes_length);
|
||||||
hashmap_GC_to_array(object->value.as_hashmap, &keys, &keys_length);
|
|
||||||
char *string_obj = "{";
|
char *string_obj = "{";
|
||||||
size_t length = strlen(string_obj);
|
size_t length = strlen(string_obj);
|
||||||
string = realloc(string, string_length + length);
|
string = realloc(string, string_length + length);
|
||||||
memcpy(string + string_length, string_obj, length);
|
memcpy(string + string_length, string_obj, length);
|
||||||
string_length += length;
|
string_length += length;
|
||||||
for (size_t i = 0; i < keys_length; i++) {
|
for (size_t i = 0; i < nodes_length; i++) {
|
||||||
struct node_GC node = keys[i];
|
struct node_GC *node = nodes[i];
|
||||||
ArgonObject *key = node.key;
|
ArgonObject *key = node->key;
|
||||||
ArgonObject *value = node.val;
|
ArgonObject *value = node->val;
|
||||||
|
|
||||||
|
if (!key) { fprintf(stderr, "NULL key at node %zu\n", i); continue; }
|
||||||
|
if (!value) { fprintf(stderr, "NULL value at node %zu\n", i); continue; }
|
||||||
|
|
||||||
ArgonObject *string_convert_method = get_builtin_field_for_class(
|
ArgonObject *string_convert_method = get_builtin_field_for_class(
|
||||||
get_builtin_field(key, __class__), __repr__, key);
|
get_builtin_field(key, __class__), __repr__, key);
|
||||||
@@ -102,7 +104,7 @@ ArgonObject *create_ARGON_DICTIONARY_TYPE___string__(size_t argc,
|
|||||||
string_length += length;
|
string_length += length;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i != keys_length - 1) {
|
if (i != nodes_length - 1) {
|
||||||
char *string_obj = ", ";
|
char *string_obj = ", ";
|
||||||
size_t length = strlen(string_obj);
|
size_t length = strlen(string_obj);
|
||||||
string = realloc(string, string_length + length);
|
string = realloc(string, string_length + length);
|
||||||
@@ -120,14 +122,14 @@ ArgonObject *create_ARGON_DICTIONARY_TYPE___string__(size_t argc,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArgonObject *create_ARGON_DICTIONARY_TYPE___get_attr__(size_t argc,
|
ArgonObject *create_ARGON_DICTIONARY_TYPE___getattr__(size_t argc,
|
||||||
ArgonObject **argv,
|
ArgonObject **argv,
|
||||||
ArErr *err,
|
ArErr *err,
|
||||||
RuntimeState *state) {
|
RuntimeState *state) {
|
||||||
(void)state;
|
(void)state;
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
*err = create_err(0, 0, 0, "", "Runtime Error",
|
*err = create_err(0, 0, 0, "", "Runtime Error",
|
||||||
"__get_attr__ expects 2 argument, got %" PRIu64, argc);
|
"__getattr__ expects 2 argument, got %" PRIu64, argc);
|
||||||
return ARGON_NULL;
|
return ARGON_NULL;
|
||||||
}
|
}
|
||||||
ArgonObject *object = argv[0];
|
ArgonObject *object = argv[0];
|
||||||
@@ -146,14 +148,62 @@ ArgonObject *create_ARGON_DICTIONARY_TYPE___get_attr__(size_t argc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ArgonObject *create_ARGON_DICTIONARY_TYPE___set_attr__(size_t argc,
|
ArgonObject *create_ARGON_DICTIONARY_TYPE___setattr__(size_t argc,
|
||||||
ArgonObject **argv,
|
ArgonObject **argv,
|
||||||
ArErr *err,
|
ArErr *err,
|
||||||
RuntimeState *state) {
|
RuntimeState *state) {
|
||||||
(void)state;
|
(void)state;
|
||||||
if (argc != 3) {
|
if (argc != 3) {
|
||||||
*err = create_err(0, 0, 0, "", "Runtime Error",
|
*err = create_err(0, 0, 0, "", "Runtime Error",
|
||||||
"__set_attr__ expects 2 argument, got %" PRIu64, argc);
|
"__setattr__ expects 2 argument, got %" PRIu64, argc);
|
||||||
|
return ARGON_NULL;
|
||||||
|
}
|
||||||
|
ArgonObject *object = argv[0];
|
||||||
|
ArgonObject *key = argv[1];
|
||||||
|
ArgonObject *value = argv[2];
|
||||||
|
int64_t hash = hash_object(key, err, state);
|
||||||
|
if (err->exists) {
|
||||||
|
return ARGON_NULL;
|
||||||
|
}
|
||||||
|
hashmap_insert_GC(object->value.as_hashmap, hash, key, value, 0);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArgonObject *create_ARGON_DICTIONARY_TYPE___getitem__(size_t argc,
|
||||||
|
ArgonObject **argv,
|
||||||
|
ArErr *err,
|
||||||
|
RuntimeState *state) {
|
||||||
|
(void)state;
|
||||||
|
if (argc != 2) {
|
||||||
|
*err = create_err(0, 0, 0, "", "Runtime Error",
|
||||||
|
"__getitem__ expects 2 argument, got %" PRIu64, argc);
|
||||||
|
return ARGON_NULL;
|
||||||
|
}
|
||||||
|
ArgonObject *object = argv[0];
|
||||||
|
ArgonObject *key = argv[1];
|
||||||
|
int64_t hash = hash_object(key, err, state);
|
||||||
|
if (err->exists) {
|
||||||
|
return ARGON_NULL;
|
||||||
|
}
|
||||||
|
ArgonObject *result = hashmap_lookup_GC(object->value.as_hashmap, hash);
|
||||||
|
if (!result) {
|
||||||
|
char *object_str = argon_object_to_null_terminated_string(key, err, state);
|
||||||
|
|
||||||
|
*err = create_err(0, 0, 0, NULL, "Attribute Error",
|
||||||
|
"Dictionary has no item '%s'", object_str);
|
||||||
|
return ARGON_NULL;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArgonObject *create_ARGON_DICTIONARY_TYPE___setitem__(size_t argc,
|
||||||
|
ArgonObject **argv,
|
||||||
|
ArErr *err,
|
||||||
|
RuntimeState *state) {
|
||||||
|
(void)state;
|
||||||
|
if (argc != 3) {
|
||||||
|
*err = create_err(0, 0, 0, "", "Runtime Error",
|
||||||
|
"__setitem__ expects 2 argument, got %" PRIu64, argc);
|
||||||
return ARGON_NULL;
|
return ARGON_NULL;
|
||||||
}
|
}
|
||||||
ArgonObject *object = argv[0];
|
ArgonObject *object = argv[0];
|
||||||
@@ -175,13 +225,21 @@ void create_ARGON_DICTIONARY_TYPE() {
|
|||||||
create_argon_native_function(
|
create_argon_native_function(
|
||||||
"__init__", create_ARGON_DICTIONARY_TYPE___init__));
|
"__init__", create_ARGON_DICTIONARY_TYPE___init__));
|
||||||
add_builtin_field(
|
add_builtin_field(
|
||||||
ARGON_DICTIONARY_TYPE, __get_attr__,
|
ARGON_DICTIONARY_TYPE, __getattr__,
|
||||||
create_argon_native_function("__get_attr__",
|
create_argon_native_function("__getattr__",
|
||||||
create_ARGON_DICTIONARY_TYPE___get_attr__));
|
create_ARGON_DICTIONARY_TYPE___getattr__));
|
||||||
add_builtin_field(
|
add_builtin_field(
|
||||||
ARGON_DICTIONARY_TYPE, __set_attr__,
|
ARGON_DICTIONARY_TYPE, __setattr__,
|
||||||
create_argon_native_function("__set_attr__",
|
create_argon_native_function("__setattr__",
|
||||||
create_ARGON_DICTIONARY_TYPE___set_attr__));
|
create_ARGON_DICTIONARY_TYPE___setattr__));
|
||||||
|
add_builtin_field(
|
||||||
|
ARGON_DICTIONARY_TYPE, __setitem__,
|
||||||
|
create_argon_native_function("__setitem__",
|
||||||
|
create_ARGON_DICTIONARY_TYPE___setitem__));
|
||||||
|
add_builtin_field(
|
||||||
|
ARGON_DICTIONARY_TYPE, __getitem__,
|
||||||
|
create_argon_native_function("__getitem__",
|
||||||
|
create_ARGON_DICTIONARY_TYPE___getitem__));
|
||||||
add_builtin_field(ARGON_DICTIONARY_TYPE, __string__,
|
add_builtin_field(ARGON_DICTIONARY_TYPE, __string__,
|
||||||
create_argon_native_function(
|
create_argon_native_function(
|
||||||
"__string__", create_ARGON_DICTIONARY_TYPE___string__));
|
"__string__", create_ARGON_DICTIONARY_TYPE___string__));
|
||||||
|
|||||||
@@ -32,12 +32,12 @@ void load_argon_function(Translated *translated, RuntimeState *state,
|
|||||||
add_builtin_field(object, __name__,
|
add_builtin_field(object, __name__,
|
||||||
new_string_object(arena_get(&translated->constants, offset),
|
new_string_object(arena_get(&translated->constants, offset),
|
||||||
length, 0, 0));
|
length, 0, 0));
|
||||||
object->value.argon_fn = ar_alloc(sizeof(struct argon_function_struct));
|
uint64_t number_of_parameters = pop_bytecode(translated, state);
|
||||||
object->value.argon_fn->translated = *translated;
|
object->value.argon_fn = ar_alloc(sizeof(struct argon_function_struct)+number_of_parameters *
|
||||||
object->value.argon_fn->number_of_parameters = pop_bytecode(translated, state);
|
|
||||||
object->value.argon_fn->parameters =
|
|
||||||
ar_alloc(object->value.argon_fn->number_of_parameters *
|
|
||||||
sizeof(struct string_struct));
|
sizeof(struct string_struct));
|
||||||
|
object->value.argon_fn->parameters = (struct string_struct*)((char*)object->value.argon_fn+sizeof(struct argon_function_struct));
|
||||||
|
object->value.argon_fn->translated = *translated;
|
||||||
|
object->value.argon_fn->number_of_parameters = number_of_parameters;
|
||||||
for (size_t i = 0; i < object->value.argon_fn->number_of_parameters; i++) {
|
for (size_t i = 0; i < object->value.argon_fn->number_of_parameters; i++) {
|
||||||
offset = pop_bytecode(translated, state);
|
offset = pop_bytecode(translated, state);
|
||||||
length = pop_bytecode(translated, state);
|
length = pop_bytecode(translated, state);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
ArgonObject *ARGON_NUMBER_TYPE;
|
ArgonObject *ARGON_NUMBER_TYPE;
|
||||||
|
|
||||||
@@ -268,6 +269,64 @@ ArgonObject *ARGON_NUMBER_TYPE___multiply__(size_t argc, ArgonObject **argv,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static inline uint64_t mix64(uint64_t x) {
|
||||||
|
x ^= x >> 33;
|
||||||
|
x *= 0xff51afd7ed558ccdULL;
|
||||||
|
x ^= x >> 33;
|
||||||
|
x *= 0xc4ceb9fe1a85ec53ULL;
|
||||||
|
x ^= x >> 33;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t hash_mpz(const mpz_t z) {
|
||||||
|
// Export to raw bytes (big-endian for consistency)
|
||||||
|
size_t count;
|
||||||
|
unsigned char *data = mpz_export(NULL, &count, 1, 1, 1, 0, z);
|
||||||
|
|
||||||
|
// FNV-1a over bytes
|
||||||
|
uint64_t h = 1469598103934665603ULL;
|
||||||
|
for (size_t i = 0; i < count; i++) {
|
||||||
|
h ^= data[i];
|
||||||
|
h *= 1099511628211ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Include sign bit
|
||||||
|
if (mpz_sgn(z) < 0)
|
||||||
|
h = ~h;
|
||||||
|
|
||||||
|
// Free the temporary buffer allocated by mpz_export
|
||||||
|
free(data);
|
||||||
|
|
||||||
|
return mix64(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t hash_mpq(mpq_t q) {
|
||||||
|
uint64_t h_num = hash_mpz(mpq_numref(q));
|
||||||
|
uint64_t h_den = hash_mpz(mpq_denref(q));
|
||||||
|
|
||||||
|
// Combine using a standard 64-bit hash mix (boost-style)
|
||||||
|
uint64_t h = h_num ^ (h_den + 0x9e3779b97f4a7c15ULL + (h_num << 6) + (h_num >> 2));
|
||||||
|
return mix64(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArgonObject *ARGON_NUMBER_TYPE___hash__(size_t argc, ArgonObject **argv,
|
||||||
|
ArErr *err, RuntimeState *state) {
|
||||||
|
(void)state;
|
||||||
|
if (argc != 1) {
|
||||||
|
*err = create_err(0, 0, 0, "", "Runtime Error",
|
||||||
|
"__hash__ expects 1 arguments, got %" PRIu64, argc);
|
||||||
|
}
|
||||||
|
uint64_t hash;
|
||||||
|
if (argv[0]->value.as_number->is_int64) {
|
||||||
|
hash = mix64(argv[0]->value.as_number->n.i64);
|
||||||
|
} else {
|
||||||
|
hash = hash_mpq(*argv[0]->value.as_number->n.mpq);
|
||||||
|
}
|
||||||
|
return new_number_object_from_int64(hash);
|
||||||
|
}
|
||||||
|
|
||||||
ArgonObject *ARGON_NUMBER_TYPE___division__(size_t argc, ArgonObject **argv,
|
ArgonObject *ARGON_NUMBER_TYPE___division__(size_t argc, ArgonObject **argv,
|
||||||
ArErr *err, RuntimeState *state) {
|
ArErr *err, RuntimeState *state) {
|
||||||
(void)state;
|
(void)state;
|
||||||
@@ -497,7 +556,6 @@ void init_small_ints() {
|
|||||||
for (int64_t i = 0; i <= small_ints_max - small_ints_min; i++) {
|
for (int64_t i = 0; i <= small_ints_max - small_ints_min; i++) {
|
||||||
int64_t n = i + small_ints_min;
|
int64_t n = i + small_ints_min;
|
||||||
small_ints[i].type = TYPE_NUMBER;
|
small_ints[i].type = TYPE_NUMBER;
|
||||||
small_ints[i].built_in_slot_length = 0;
|
|
||||||
small_ints[i].dict = NULL;
|
small_ints[i].dict = NULL;
|
||||||
small_ints[i].value.as_number = &small_ints_as_number[i];
|
small_ints[i].value.as_number = &small_ints_as_number[i];
|
||||||
add_builtin_field(&small_ints[i], __class__, ARGON_NUMBER_TYPE);
|
add_builtin_field(&small_ints[i], __class__, ARGON_NUMBER_TYPE);
|
||||||
@@ -520,6 +578,9 @@ void create_ARGON_NUMBER_TYPE() {
|
|||||||
add_builtin_field(
|
add_builtin_field(
|
||||||
ARGON_NUMBER_TYPE, __number__,
|
ARGON_NUMBER_TYPE, __number__,
|
||||||
create_argon_native_function("__number__", ARGON_NUMBER_TYPE___number__));
|
create_argon_native_function("__number__", ARGON_NUMBER_TYPE___number__));
|
||||||
|
add_builtin_field(
|
||||||
|
ARGON_NUMBER_TYPE, __hash__,
|
||||||
|
create_argon_native_function("__hash__", ARGON_NUMBER_TYPE___hash__));
|
||||||
add_builtin_field(ARGON_NUMBER_TYPE, __boolean__,
|
add_builtin_field(ARGON_NUMBER_TYPE, __boolean__,
|
||||||
create_argon_native_function(
|
create_argon_native_function(
|
||||||
"__boolean__", ARGON_NUMBER_TYPE___boolean__));
|
"__boolean__", ARGON_NUMBER_TYPE___boolean__));
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ const char *built_in_field_names[BUILT_IN_FIELDS_COUNT] = {
|
|||||||
"__class__",
|
"__class__",
|
||||||
"__name__",
|
"__name__",
|
||||||
"", // above is anything that gets stored in built in slots
|
"", // above is anything that gets stored in built in slots
|
||||||
|
"__binding__",
|
||||||
|
"__function__",
|
||||||
"__add__",
|
"__add__",
|
||||||
"__string__",
|
"__string__",
|
||||||
"__subtract__",
|
"__subtract__",
|
||||||
@@ -43,15 +45,15 @@ const char *built_in_field_names[BUILT_IN_FIELDS_COUNT] = {
|
|||||||
"__new__",
|
"__new__",
|
||||||
"__init__",
|
"__init__",
|
||||||
"__boolean__",
|
"__boolean__",
|
||||||
"__get_attr__",
|
"__getattr__",
|
||||||
"__binding__",
|
"__getitem__",
|
||||||
"__function__",
|
|
||||||
"address",
|
"address",
|
||||||
"__call__",
|
"__call__",
|
||||||
"__number__",
|
"__number__",
|
||||||
"length",
|
"length",
|
||||||
"__getattribute__",
|
"__getattribute__",
|
||||||
"__set_attr__",
|
"__setattr__",
|
||||||
|
"__setitem__",
|
||||||
"__hash__",
|
"__hash__",
|
||||||
"__repr__"};
|
"__repr__"};
|
||||||
|
|
||||||
@@ -77,9 +79,7 @@ int64_t hash_object(ArgonObject *object, ArErr *err, RuntimeState *state) {
|
|||||||
ArgonObject *hash_function = get_builtin_field_for_class(
|
ArgonObject *hash_function = get_builtin_field_for_class(
|
||||||
get_builtin_field(object, __class__), __hash__, object);
|
get_builtin_field(object, __class__), __hash__, object);
|
||||||
if (!hash_function) {
|
if (!hash_function) {
|
||||||
*err = create_err(err->line, err->column, err->length, err->path,
|
return (int64_t)object;
|
||||||
"Hash Error", "objects class has no __hash__ method");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
ArgonObject *hash_result = argon_call(hash_function, 0, NULL, err, state);
|
ArgonObject *hash_result = argon_call(hash_function, 0, NULL, err, state);
|
||||||
if (hash_result->type != TYPE_NUMBER ||
|
if (hash_result->type != TYPE_NUMBER ||
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
extern ArgonObject *BASE_CLASS;
|
extern ArgonObject *BASE_CLASS;
|
||||||
|
|
||||||
|
extern const char *built_in_field_names[BUILT_IN_FIELDS_COUNT];
|
||||||
|
|
||||||
typedef struct ArgonObject ArgonObject;
|
typedef struct ArgonObject ArgonObject;
|
||||||
|
|
||||||
ArgonObject *new_class();
|
ArgonObject *new_class();
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
#include "../../call/call.h"
|
||||||
#include "../number/number.h"
|
#include "../number/number.h"
|
||||||
#include "../object.h"
|
#include "../object.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -14,14 +15,12 @@
|
|||||||
|
|
||||||
ArgonObject *ARGON_STRING_TYPE = NULL;
|
ArgonObject *ARGON_STRING_TYPE = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char *c_quote_string(const char *input, size_t len) {
|
char *c_quote_string(const char *input, size_t len) {
|
||||||
// Worst case: every byte becomes "\uXXXX" (6 chars) + quotes + NUL
|
// Worst case: every byte becomes "\uXXXX" (6 chars) + quotes + NUL
|
||||||
size_t max_out = 2 + (len * 6) + 1;
|
size_t max_out = 2 + (len * 6) + 1;
|
||||||
char *out = malloc(max_out);
|
char *out = malloc(max_out);
|
||||||
if (!out) return NULL;
|
if (!out)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
size_t j = 0;
|
size_t j = 0;
|
||||||
out[j++] = '"';
|
out[j++] = '"';
|
||||||
@@ -31,15 +30,25 @@ char *c_quote_string(const char *input, size_t len) {
|
|||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '\n':
|
case '\n':
|
||||||
out[j++] = '\\'; out[j++] = 'n'; break;
|
out[j++] = '\\';
|
||||||
|
out[j++] = 'n';
|
||||||
|
break;
|
||||||
case '\t':
|
case '\t':
|
||||||
out[j++] = '\\'; out[j++] = 't'; break;
|
out[j++] = '\\';
|
||||||
|
out[j++] = 't';
|
||||||
|
break;
|
||||||
case '\r':
|
case '\r':
|
||||||
out[j++] = '\\'; out[j++] = 'r'; break;
|
out[j++] = '\\';
|
||||||
|
out[j++] = 'r';
|
||||||
|
break;
|
||||||
case '\\':
|
case '\\':
|
||||||
out[j++] = '\\'; out[j++] = '\\'; break;
|
out[j++] = '\\';
|
||||||
|
out[j++] = '\\';
|
||||||
|
break;
|
||||||
case '\"':
|
case '\"':
|
||||||
out[j++] = '\\'; out[j++] = '\"'; break;
|
out[j++] = '\\';
|
||||||
|
out[j++] = '\"';
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (isprint(c)) {
|
if (isprint(c)) {
|
||||||
out[j++] = c;
|
out[j++] = c;
|
||||||
@@ -55,10 +64,9 @@ char *c_quote_string(const char *input, size_t len) {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_string(ArgonObject*object,char *data, size_t length, uint64_t prehash,
|
void init_string(ArgonObject *object, char *data, size_t length,
|
||||||
uint64_t hash) {
|
uint64_t prehash, uint64_t hash) {
|
||||||
add_builtin_field(object, field_length,
|
add_builtin_field(object, field_length, new_number_object_from_int64(length));
|
||||||
new_number_object_from_int64(length));
|
|
||||||
object->type = TYPE_STRING;
|
object->type = TYPE_STRING;
|
||||||
object->value.as_str = ar_alloc(sizeof(struct string_struct));
|
object->value.as_str = ar_alloc(sizeof(struct string_struct));
|
||||||
object->value.as_str->data = data;
|
object->value.as_str->data = data;
|
||||||
@@ -69,8 +77,8 @@ void init_string(ArgonObject*object,char *data, size_t length, uint64_t prehash,
|
|||||||
object->as_bool = length;
|
object->as_bool = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArgonObject *new_string_object_without_memcpy(char *data, size_t length, uint64_t prehash,
|
ArgonObject *new_string_object_without_memcpy(char *data, size_t length,
|
||||||
uint64_t hash) {
|
uint64_t prehash, uint64_t hash) {
|
||||||
ArgonObject *object = new_instance(ARGON_STRING_TYPE);
|
ArgonObject *object = new_instance(ARGON_STRING_TYPE);
|
||||||
init_string(object, data, length, prehash, hash);
|
init_string(object, data, length, prehash, hash);
|
||||||
return object;
|
return object;
|
||||||
@@ -83,6 +91,28 @@ ArgonObject *new_string_object(char *data, size_t length, uint64_t prehash,
|
|||||||
return new_string_object_without_memcpy(data_copy, length, prehash, hash);
|
return new_string_object_without_memcpy(data_copy, length, prehash, hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *argon_object_to_null_terminated_string(ArgonObject *object, ArErr *err,
|
||||||
|
RuntimeState *state) {
|
||||||
|
ArgonObject *string_convert_method = get_builtin_field_for_class(
|
||||||
|
get_builtin_field(object, __class__), __repr__, object);
|
||||||
|
|
||||||
|
if (!string_convert_method)
|
||||||
|
return "<object>";
|
||||||
|
|
||||||
|
ArgonObject *string_object =
|
||||||
|
argon_call(string_convert_method, 0, NULL, err, state);
|
||||||
|
if (err->exists)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
|
||||||
|
if (string_object->type != TYPE_STRING) return "<object>";
|
||||||
|
|
||||||
|
char *string = ar_alloc(string_object->value.as_str->length+1);
|
||||||
|
string[string_object->value.as_str->length] = '\0';
|
||||||
|
memcpy(string, string_object->value.as_str->data, string_object->value.as_str->length);
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
ArgonObject *new_string_object_null_terminated(char *data) {
|
ArgonObject *new_string_object_null_terminated(char *data) {
|
||||||
return new_string_object(data, strlen(data), 0, 0);
|
return new_string_object(data, strlen(data), 0, 0);
|
||||||
}
|
}
|
||||||
@@ -12,13 +12,17 @@ extern ArgonObject *ARGON_STRING_TYPE;
|
|||||||
|
|
||||||
char *c_quote_string(const char *input, size_t len);
|
char *c_quote_string(const char *input, size_t len);
|
||||||
|
|
||||||
void init_string(ArgonObject*object,char *data, size_t length, uint64_t prehash,
|
void init_string(ArgonObject *object, char *data, size_t length,
|
||||||
uint64_t hash);
|
uint64_t prehash, uint64_t hash);
|
||||||
|
|
||||||
ArgonObject *new_string_object_without_memcpy(char *data, size_t length, uint64_t prehash,
|
char *argon_object_to_null_terminated_string(ArgonObject *object, ArErr *err,
|
||||||
uint64_t hash);
|
RuntimeState *state);
|
||||||
|
|
||||||
ArgonObject *new_string_object(char *data, size_t length, uint64_t prehash, uint64_t hash);
|
ArgonObject *new_string_object_without_memcpy(char *data, size_t length,
|
||||||
|
uint64_t prehash, uint64_t hash);
|
||||||
|
|
||||||
|
ArgonObject *new_string_object(char *data, size_t length, uint64_t prehash,
|
||||||
|
uint64_t hash);
|
||||||
|
|
||||||
ArgonObject *new_string_object_null_terminated(char *data);
|
ArgonObject *new_string_object_null_terminated(char *data);
|
||||||
#endif // STRING_OBJ_H
|
#endif // STRING_OBJ_H
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
#include "objects/term/term.h"
|
#include "objects/term/term.h"
|
||||||
#include "objects/type/type.h"
|
#include "objects/type/type.h"
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <gc/gc.h>
|
#include <gc.h>
|
||||||
#include <gmp.h>
|
#include <gmp.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
@@ -72,11 +72,11 @@ ArgonObject *BASE_CLASS___getattribute__(size_t argc, ArgonObject **argv,
|
|||||||
access->value.as_str->length, true, false);
|
access->value.as_str->length, true, false);
|
||||||
if (value)
|
if (value)
|
||||||
return value;
|
return value;
|
||||||
ArgonObject *cls__get_attr__ = get_builtin_field_for_class(
|
ArgonObject *cls__getattr__ = get_builtin_field_for_class(
|
||||||
get_builtin_field(to_access, __class__), __get_attr__, to_access);
|
get_builtin_field(to_access, __class__), __getattr__, to_access);
|
||||||
if (cls__get_attr__) {
|
if (cls__getattr__) {
|
||||||
value =
|
value =
|
||||||
argon_call(cls__get_attr__, 1, (ArgonObject *[]){access}, err, state);
|
argon_call(cls__getattr__, 1, (ArgonObject *[]){access}, err, state);
|
||||||
if (err->exists) {
|
if (err->exists) {
|
||||||
return ARGON_NULL;
|
return ARGON_NULL;
|
||||||
}
|
}
|
||||||
@@ -285,12 +285,12 @@ ArgonObject *BASE_CLASS___init__(size_t argc, ArgonObject **argv, ArErr *err,
|
|||||||
return ARGON_NULL;
|
return ARGON_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArgonObject *BASE_CLASS___set_attr__(size_t argc, ArgonObject **argv, ArErr *err,
|
ArgonObject *BASE_CLASS___setattr__(size_t argc, ArgonObject **argv, ArErr *err,
|
||||||
RuntimeState *state) {
|
RuntimeState *state) {
|
||||||
(void)state;
|
(void)state;
|
||||||
if (argc != 3) {
|
if (argc != 3) {
|
||||||
*err = create_err(0, 0, 0, "", "Runtime Error",
|
*err = create_err(0, 0, 0, "", "Runtime Error",
|
||||||
"__set_attr__ expects 3 argument, got %" PRIu64, argc);
|
"__setattr__ expects 3 argument, got %" PRIu64, argc);
|
||||||
}
|
}
|
||||||
if (!argv[1]->value.as_str->hash)
|
if (!argv[1]->value.as_str->hash)
|
||||||
argv[1]->value.as_str->hash =
|
argv[1]->value.as_str->hash =
|
||||||
@@ -615,7 +615,6 @@ void bootstrap_types() {
|
|||||||
add_builtin_field(ARGON_METHOD_TYPE, __base__, BASE_CLASS);
|
add_builtin_field(ARGON_METHOD_TYPE, __base__, BASE_CLASS);
|
||||||
add_builtin_field(ARGON_METHOD_TYPE, __name__,
|
add_builtin_field(ARGON_METHOD_TYPE, __name__,
|
||||||
new_string_object_null_terminated("method"));
|
new_string_object_null_terminated("method"));
|
||||||
create_ARGON_NUMBER_TYPE();
|
|
||||||
|
|
||||||
add_builtin_field(
|
add_builtin_field(
|
||||||
BASE_CLASS, __new__,
|
BASE_CLASS, __new__,
|
||||||
@@ -692,12 +691,14 @@ void bootstrap_types() {
|
|||||||
create_argon_native_function("__getattribute__",
|
create_argon_native_function("__getattribute__",
|
||||||
BASE_CLASS___getattribute__));
|
BASE_CLASS___getattribute__));
|
||||||
add_builtin_field(
|
add_builtin_field(
|
||||||
BASE_CLASS, __set_attr__,
|
BASE_CLASS, __setattr__,
|
||||||
create_argon_native_function("__set_attr__", BASE_CLASS___set_attr__));
|
create_argon_native_function("__setattr__", BASE_CLASS___setattr__));
|
||||||
create_ARGON_DICTIONARY_TYPE();
|
create_ARGON_DICTIONARY_TYPE();
|
||||||
|
create_ARGON_NUMBER_TYPE();
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_to_hashmap(struct hashmap_GC *hashmap, char *name, ArgonObject *value) {
|
void add_to_hashmap(struct hashmap_GC *hashmap, char *name,
|
||||||
|
ArgonObject *value) {
|
||||||
size_t length = strlen(name);
|
size_t length = strlen(name);
|
||||||
uint64_t hash = siphash64_bytes(name, length, siphash_key);
|
uint64_t hash = siphash64_bytes(name, length, siphash_key);
|
||||||
ArgonObject *key = new_string_object(name, length, 0, hash);
|
ArgonObject *key = new_string_object(name, length, 0, hash);
|
||||||
@@ -722,12 +723,12 @@ void bootstrap_globals() {
|
|||||||
create_argon_native_function("log", term_log));
|
create_argon_native_function("log", term_log));
|
||||||
add_to_scope(Global_Scope, "term", create_dictionary(argon_term));
|
add_to_scope(Global_Scope, "term", create_dictionary(argon_term));
|
||||||
|
|
||||||
|
|
||||||
struct hashmap_GC *environment_variables = createHashmap_GC();
|
struct hashmap_GC *environment_variables = createHashmap_GC();
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
// Windows: use WinAPI
|
// Windows: use WinAPI
|
||||||
LPCH env = GetEnvironmentStringsA();
|
LPCH env = GetEnvironmentStringsA();
|
||||||
if (!env) return;
|
if (!env)
|
||||||
|
return;
|
||||||
|
|
||||||
for (LPCH var = env; *var; var += strlen(var) + 1) {
|
for (LPCH var = env; *var; var += strlen(var) + 1) {
|
||||||
// Each string is like "KEY=VALUE"
|
// Each string is like "KEY=VALUE"
|
||||||
@@ -742,7 +743,8 @@ void bootstrap_globals() {
|
|||||||
|
|
||||||
const char *value = getenv(key);
|
const char *value = getenv(key);
|
||||||
add_to_hashmap(environment_variables, key,
|
add_to_hashmap(environment_variables, key,
|
||||||
value?new_string_object_null_terminated((char *)value):ARGON_NULL);
|
value ? new_string_object_null_terminated((char *)value)
|
||||||
|
: ARGON_NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -761,7 +763,8 @@ void bootstrap_globals() {
|
|||||||
|
|
||||||
const char *value = getenv(key);
|
const char *value = getenv(key);
|
||||||
add_to_hashmap(environment_variables, key,
|
add_to_hashmap(environment_variables, key,
|
||||||
value?new_string_object_null_terminated((char *)value):ARGON_NULL);
|
value ? new_string_object_null_terminated((char *)value)
|
||||||
|
: ARGON_NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -885,7 +888,10 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack,
|
|||||||
[OP_MULTIPLICATION] = &&DO_MULTIPLICATION,
|
[OP_MULTIPLICATION] = &&DO_MULTIPLICATION,
|
||||||
[OP_DIVISION] = &&DO_DIVISION,
|
[OP_DIVISION] = &&DO_DIVISION,
|
||||||
[OP_NOT] = &&DO_NOT,
|
[OP_NOT] = &&DO_NOT,
|
||||||
[OP_LOAD_SETATTR_METHOD] = &&DO_LOAD_SETATTR_METHOD};
|
[OP_LOAD_SETATTR_METHOD] = &&DO_LOAD_SETATTR_METHOD,
|
||||||
|
[OP_CREATE_DICTIONARY] = &&DO_CREATE_DICTIONARY,
|
||||||
|
[OP_LOAD_SETITEM_METHOD] = &&DO_LOAD_SETITEM_METHOD,
|
||||||
|
[OP_LOAD_GETITEM_METHOD] = &&DO_LOAD_GETITEM_METHOD};
|
||||||
_state.head = 0;
|
_state.head = 0;
|
||||||
|
|
||||||
StackFrame *currentStackFrame = ar_alloc(sizeof(StackFrame));
|
StackFrame *currentStackFrame = ar_alloc(sizeof(StackFrame));
|
||||||
@@ -1257,13 +1263,41 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack,
|
|||||||
}
|
}
|
||||||
DO_LOAD_SETATTR_METHOD: {
|
DO_LOAD_SETATTR_METHOD: {
|
||||||
state->registers[0] = get_builtin_field_for_class(
|
state->registers[0] = get_builtin_field_for_class(
|
||||||
get_builtin_field(state->registers[0], __class__), __set_attr__,
|
get_builtin_field(state->registers[0], __class__), __setattr__,
|
||||||
state->registers[0]);
|
state->registers[0]);
|
||||||
if (!state->registers[0]) {
|
if (!state->registers[0]) {
|
||||||
*err = create_err(
|
*err = create_err(
|
||||||
state->source_location.line, state->source_location.column,
|
state->source_location.line, state->source_location.column,
|
||||||
state->source_location.length, state->path, "Runtime Error",
|
state->source_location.length, state->path, "Runtime Error",
|
||||||
"unable to get __set_attr__ from objects class");
|
"unable to get __setattr__ from objects class");
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
DO_CREATE_DICTIONARY: {
|
||||||
|
state->registers[0] = create_dictionary(createHashmap_GC());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
DO_LOAD_SETITEM_METHOD: {
|
||||||
|
state->registers[0] = get_builtin_field_for_class(
|
||||||
|
get_builtin_field(state->registers[0], __class__), __setitem__,
|
||||||
|
state->registers[0]);
|
||||||
|
if (!state->registers[0]) {
|
||||||
|
*err = create_err(
|
||||||
|
state->source_location.line, state->source_location.column,
|
||||||
|
state->source_location.length, state->path, "Runtime Error",
|
||||||
|
"unable to get __setitem__ from objects class");
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
DO_LOAD_GETITEM_METHOD: {
|
||||||
|
state->registers[0] = get_builtin_field_for_class(
|
||||||
|
get_builtin_field(state->registers[0], __class__), __getitem__,
|
||||||
|
state->registers[0]);
|
||||||
|
if (!state->registers[0]) {
|
||||||
|
*err = create_err(
|
||||||
|
state->source_location.line, state->source_location.column,
|
||||||
|
state->source_location.length, state->path, "Runtime Error",
|
||||||
|
"unable to get __getitem__ from objects class");
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
#define likely(x) __builtin_expect(!!(x), 1)
|
#define likely(x) __builtin_expect(!!(x), 1)
|
||||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||||
|
|
||||||
|
#define MAX_REGISTERS 256
|
||||||
|
|
||||||
extern ArgonObject *ARGON_METHOD_TYPE;
|
extern ArgonObject *ARGON_METHOD_TYPE;
|
||||||
extern Stack *Global_Scope;
|
extern Stack *Global_Scope;
|
||||||
|
|
||||||
|
|||||||
45
src/shell.c
45
src/shell.c
@@ -23,6 +23,7 @@
|
|||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#endif
|
#endif
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
#include <windows.h>
|
||||||
FILE *fmemopen(void *buf, size_t size, const char *mode) {
|
FILE *fmemopen(void *buf, size_t size, const char *mode) {
|
||||||
if (strchr(mode, 'r') == NULL) {
|
if (strchr(mode, 'r') == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -41,6 +42,46 @@ FILE *fmemopen(void *buf, size_t size, const char *mode) {
|
|||||||
|
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only define ssize_t if it doesn't already exist
|
||||||
|
#ifndef _SSIZE_T_DEFINED
|
||||||
|
typedef long ssize_t;
|
||||||
|
#define _SSIZE_T_DEFINED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ssize_t getline(char **lineptr, size_t *n, FILE *stream) {
|
||||||
|
if (!lineptr || !n || !stream)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
size_t pos = 0;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
if (*lineptr == NULL || *n == 0) {
|
||||||
|
*n = 128;
|
||||||
|
*lineptr = malloc(*n);
|
||||||
|
if (!*lineptr)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((c = fgetc(stream)) != EOF) {
|
||||||
|
if (pos + 1 >= *n) {
|
||||||
|
*n *= 2;
|
||||||
|
char *tmp = realloc(*lineptr, *n);
|
||||||
|
if (!tmp)
|
||||||
|
return -1;
|
||||||
|
*lineptr = tmp;
|
||||||
|
}
|
||||||
|
(*lineptr)[pos++] = c;
|
||||||
|
if (c == '\n')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos == 0 && c == EOF)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
(*lineptr)[pos] = '\0';
|
||||||
|
return (ssize_t)pos;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
#include "../external/linenoise/linenoise.h"
|
#include "../external/linenoise/linenoise.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -171,7 +212,6 @@ char *read_all_stdin(size_t *out_len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int shell() {
|
int shell() {
|
||||||
|
|
||||||
Stack *main_scope = create_scope(Global_Scope, true);
|
Stack *main_scope = create_scope(Global_Scope, true);
|
||||||
|
|
||||||
if (!isatty(STDIN_FILENO)) {
|
if (!isatty(STDIN_FILENO)) {
|
||||||
@@ -274,7 +314,8 @@ int shell() {
|
|||||||
if (resp) {
|
if (resp) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (runtime_state.registers[0]&&runtime_state.registers[0] != ARGON_NULL) {
|
if (runtime_state.registers[0] &&
|
||||||
|
runtime_state.registers[0] != ARGON_NULL) {
|
||||||
ArErr err = no_err;
|
ArErr err = no_err;
|
||||||
argon_call(output_object, 1,
|
argon_call(output_object, 1,
|
||||||
(ArgonObject *[]){runtime_state.registers[0]}, &err,
|
(ArgonObject *[]){runtime_state.registers[0]}, &err,
|
||||||
|
|||||||
@@ -122,11 +122,11 @@ sets the source location onto the runtime
|
|||||||
|
|
||||||
## OP_LOAD_GETATTRIBUTE_METHOD
|
## OP_LOAD_GETATTRIBUTE_METHOD
|
||||||
|
|
||||||
loads the \_\_getattribute\_\_ method from the objects class in register 1 and put it into register 1
|
loads the \_\_getattribute\_\_ method from the objects class in register 0 and put it into register 0
|
||||||
|
|
||||||
## OP_LOAD_BOOL
|
## OP_LOAD_BOOL
|
||||||
|
|
||||||
loads a boolean into register 1
|
loads a boolean into register 0
|
||||||
|
|
||||||
1. byte representing true or false (1 or 0) *
|
1. byte representing true or false (1 or 0) *
|
||||||
|
|
||||||
@@ -187,4 +187,16 @@ inverts the boolean value in register 0.
|
|||||||
|
|
||||||
## OP_LOAD_SETATTR_METHOD
|
## OP_LOAD_SETATTR_METHOD
|
||||||
|
|
||||||
loads the \_\_setattr\_\_ method from the objects class in register 1 and put it into register 1
|
loads the \_\_setattr\_\_ method from the objects class in register 0 and put it into register 0
|
||||||
|
|
||||||
|
## OP_CREATE_DICTIONARY
|
||||||
|
|
||||||
|
create a dictionary object into register 0.
|
||||||
|
|
||||||
|
## OP_LOAD_GETITEM_METHOD
|
||||||
|
|
||||||
|
loads the \_\_getitem\_\_ method from the objects class in register 0 and put it into register 0
|
||||||
|
|
||||||
|
## OP_LOAD_SETITEM_METHOD
|
||||||
|
|
||||||
|
loads the \_\_setitem\_\_ method from the objects class in register 0 and put it into register 0
|
||||||
33
src/translator/item_access/item_access.c
Normal file
33
src/translator/item_access/item_access.c
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 William Bell
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
#include "item_access.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
size_t translate_item_access(Translated *translated, ParsedItemAccess *access,
|
||||||
|
ArErr *err) {
|
||||||
|
set_registers(translated, 1);
|
||||||
|
uint64_t first = translate_parsed(translated, access->to_access, err);
|
||||||
|
if (err->exists)
|
||||||
|
return 0;
|
||||||
|
push_instruction_byte(translated, OP_LOAD_GETITEM_METHOD);
|
||||||
|
push_instruction_byte(translated, OP_INIT_CALL);
|
||||||
|
push_instruction_code(translated, access->itemc);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < access->itemc; i++) {
|
||||||
|
translate_parsed(translated, access->items[i], err);
|
||||||
|
if (err->exists)
|
||||||
|
return 0;
|
||||||
|
push_instruction_byte(translated, OP_INSERT_ARG);
|
||||||
|
push_instruction_code(translated, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
push_instruction_byte(translated, OP_SOURCE_LOCATION);
|
||||||
|
push_instruction_code(translated, access->line);
|
||||||
|
push_instruction_code(translated, access->column);
|
||||||
|
push_instruction_code(translated, access->length);
|
||||||
|
push_instruction_byte(translated, OP_CALL);
|
||||||
|
return first;
|
||||||
|
}
|
||||||
15
src/translator/item_access/item_access.h
Normal file
15
src/translator/item_access/item_access.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 William Bell
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef translator_item_access_H
|
||||||
|
#define translator_item_access_H
|
||||||
|
#include "../../parser/assignable/item/item.h"
|
||||||
|
#include "../translator.h"
|
||||||
|
|
||||||
|
size_t translate_item_access(Translated *translated, ParsedItemAccess *access,
|
||||||
|
ArErr *err);
|
||||||
|
|
||||||
|
#endif // translator_item_access_H
|
||||||
@@ -6,8 +6,11 @@
|
|||||||
|
|
||||||
#include "translator.h"
|
#include "translator.h"
|
||||||
#include "../hash_data/hash_data.h"
|
#include "../hash_data/hash_data.h"
|
||||||
|
#include "../parser/dictionary/dictionary.h"
|
||||||
#include "../parser/not/not.h"
|
#include "../parser/not/not.h"
|
||||||
#include "access/access.h"
|
#include "access/access.h"
|
||||||
|
#include "../parser/assignable/item/item.h"
|
||||||
|
#include "item_access/item_access.h"
|
||||||
#include "assignment/assignment.h"
|
#include "assignment/assignment.h"
|
||||||
#include "call/call.h"
|
#include "call/call.h"
|
||||||
#include "declaration/declaration.h"
|
#include "declaration/declaration.h"
|
||||||
@@ -162,6 +165,8 @@ size_t translate_parsed(Translated *translated, ParsedValue *parsedValue,
|
|||||||
err);
|
err);
|
||||||
case AST_ACCESS:
|
case AST_ACCESS:
|
||||||
return translate_access(translated, (ParsedAccess *)parsedValue->data, err);
|
return translate_access(translated, (ParsedAccess *)parsedValue->data, err);
|
||||||
|
case AST_ITEM_ACCESS:
|
||||||
|
return translate_item_access(translated, (ParsedItemAccess *)parsedValue->data, err);
|
||||||
case AST_OPERATION:
|
case AST_OPERATION:
|
||||||
return translate_operation(translated, (ParsedOperation *)parsedValue->data,
|
return translate_operation(translated, (ParsedOperation *)parsedValue->data,
|
||||||
err);
|
err);
|
||||||
@@ -176,6 +181,67 @@ size_t translate_parsed(Translated *translated, ParsedValue *parsedValue,
|
|||||||
push_instruction_byte(translated, OP_NOT);
|
push_instruction_byte(translated, OP_NOT);
|
||||||
return first;
|
return first;
|
||||||
}
|
}
|
||||||
|
case AST_DICTIONARY: {
|
||||||
|
DArray *dictionaryDarray = parsedValue->data;
|
||||||
|
|
||||||
|
size_t first = push_instruction_byte(translated, OP_CREATE_DICTIONARY);
|
||||||
|
uint8_t dictionaryRegister = translated->registerAssignment++;
|
||||||
|
|
||||||
|
push_instruction_byte(translated, OP_COPY_TO_REGISTER);
|
||||||
|
push_instruction_byte(translated, 0);
|
||||||
|
push_instruction_byte(translated, dictionaryRegister);
|
||||||
|
|
||||||
|
push_instruction_byte(translated, OP_LOAD_SETITEM_METHOD);
|
||||||
|
uint8_t setitemRegister = translated->registerAssignment++;
|
||||||
|
set_registers(translated, translated->registerAssignment);
|
||||||
|
|
||||||
|
push_instruction_byte(translated, OP_COPY_TO_REGISTER);
|
||||||
|
push_instruction_byte(translated, 0);
|
||||||
|
push_instruction_byte(translated, setitemRegister);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < dictionaryDarray->size; i++) {
|
||||||
|
ParsedDictionaryEntry *entry = darray_get(dictionaryDarray, i);
|
||||||
|
if (i != 0) {
|
||||||
|
push_instruction_byte(translated, OP_COPY_TO_REGISTER);
|
||||||
|
push_instruction_byte(translated, setitemRegister);
|
||||||
|
push_instruction_byte(translated, 0);
|
||||||
|
}
|
||||||
|
push_instruction_byte(translated, OP_INIT_CALL);
|
||||||
|
push_instruction_code(translated, 2);
|
||||||
|
|
||||||
|
translate_parsed(translated, entry->key, err);
|
||||||
|
if (err->exists)
|
||||||
|
return first;
|
||||||
|
|
||||||
|
push_instruction_byte(translated, OP_INSERT_ARG);
|
||||||
|
push_instruction_code(translated, 0);
|
||||||
|
|
||||||
|
translate_parsed(translated, entry->value, err);
|
||||||
|
if (err->exists)
|
||||||
|
return first;
|
||||||
|
|
||||||
|
push_instruction_byte(translated, OP_INSERT_ARG);
|
||||||
|
push_instruction_code(translated, 1);
|
||||||
|
|
||||||
|
push_instruction_byte(translated, OP_CALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
push_instruction_byte(translated, OP_COPY_TO_REGISTER);
|
||||||
|
push_instruction_byte(translated, dictionaryRegister);
|
||||||
|
push_instruction_byte(translated, 0);
|
||||||
|
|
||||||
|
push_instruction_byte(translated, OP_LOAD_NULL);
|
||||||
|
push_instruction_byte(translated, dictionaryRegister);
|
||||||
|
|
||||||
|
push_instruction_byte(translated, OP_LOAD_NULL);
|
||||||
|
push_instruction_byte(translated, setitemRegister);
|
||||||
|
|
||||||
|
translated->registerAssignment-=2;
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "panic: undefined translation\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,10 @@ typedef enum {
|
|||||||
OP_MULTIPLICATION,
|
OP_MULTIPLICATION,
|
||||||
OP_DIVISION,
|
OP_DIVISION,
|
||||||
OP_NOT,
|
OP_NOT,
|
||||||
OP_LOAD_SETATTR_METHOD
|
OP_LOAD_SETATTR_METHOD,
|
||||||
|
OP_CREATE_DICTIONARY,
|
||||||
|
OP_LOAD_GETITEM_METHOD,
|
||||||
|
OP_LOAD_SETITEM_METHOD
|
||||||
} OperationType;
|
} OperationType;
|
||||||
|
|
||||||
void arena_resize(ConstantArena *arena, size_t new_size);
|
void arena_resize(ConstantArena *arena, size_t new_size);
|
||||||
|
|||||||
@@ -1 +1,9 @@
|
|||||||
|
term.log("hello world")
|
||||||
term.log(()=10)
|
term.log(()=10)
|
||||||
|
term.log((x)=10)
|
||||||
|
term.log((x,y)=10)
|
||||||
|
term.log((x,y,z)=10)
|
||||||
|
term.log(a()=10)
|
||||||
|
term.log(b(x)=10)
|
||||||
|
term.log(c(x,y)=10)
|
||||||
|
term.log(d(x,y,z)=10)
|
||||||
5
tests/class_method.ar
Normal file
5
tests/class_method.ar
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
string.cool(self) = do
|
||||||
|
term.log(self, self.length)
|
||||||
|
return 10
|
||||||
|
'hello world'.cool()
|
||||||
|
string.cool('goodbye world')
|
||||||
16
tests/diff.ar
Normal file
16
tests/diff.ar
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
let h = 1e-1000
|
||||||
|
let diff(f) = (x) = (f(x + h) - f(x)) / h
|
||||||
|
|
||||||
|
|
||||||
|
let f(x) = x*x*x*x*x*x*x*x*x*x+2*x*x*x*x*x*x*x*x*x+3*x*x*x*x*x*x*x*x+4*x*x*x*x*x*x*x+5*x*x*x*x*x*x+6*x*x*x*x*x+7*x*x*x*x+8*x*x*x+9*x*x+10*x+11
|
||||||
|
let x = 100
|
||||||
|
let d = 0
|
||||||
|
|
||||||
|
do
|
||||||
|
while (true) do
|
||||||
|
let n = f(x)
|
||||||
|
term.log("f"+string(d)+"("+string(x)+") = "+string(n))
|
||||||
|
if (n) do
|
||||||
|
f = diff(f)
|
||||||
|
d = d + 1
|
||||||
|
else return
|
||||||
10
tests/factorial.ar
Normal file
10
tests/factorial.ar
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
let factorial(x) = do
|
||||||
|
let n = x-1
|
||||||
|
if (n) return x*factorial(n)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
let loop = 501
|
||||||
|
let x = 500
|
||||||
|
while (x) do
|
||||||
|
factorial(loop-x)
|
||||||
|
x=x-1
|
||||||
2
tests/hashmap_creation_seg_fault.ar
Normal file
2
tests/hashmap_creation_seg_fault.ar
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
while (true) do
|
||||||
|
{"z": 1, "b": 2, "c": 3, "a": 7}
|
||||||
23
tests/hashmap_order.ar
Normal file
23
tests/hashmap_order.ar
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
let x = {'p':1}
|
||||||
|
x.z = 1
|
||||||
|
x.b = 2
|
||||||
|
x.c = 3
|
||||||
|
x.a = 7
|
||||||
|
term.log(x)
|
||||||
|
|
||||||
|
let y = {}
|
||||||
|
y.a = 1
|
||||||
|
y.b = 2
|
||||||
|
y.c = 3
|
||||||
|
y.d = 7
|
||||||
|
y.e = 2
|
||||||
|
y.f = 3
|
||||||
|
y.g = 7
|
||||||
|
y.h = 1
|
||||||
|
y.i = 2
|
||||||
|
y.j = 3
|
||||||
|
y.k = 7
|
||||||
|
y.l = 2
|
||||||
|
y.m = 3
|
||||||
|
y.n = 7
|
||||||
|
term.log(y)
|
||||||
2
tests/hashmap_to_array_seg_fault.ar
Normal file
2
tests/hashmap_to_array_seg_fault.ar
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
while (true) do
|
||||||
|
term.log(global)
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
term.log(global)
|
|
||||||
let i = 1e8
|
|
||||||
while (i) do
|
|
||||||
i=i-1
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
i = 1000000
|
|
||||||
while i:
|
|
||||||
i=i-1
|
|
||||||
3
tests/iteration.ar
Normal file
3
tests/iteration.ar
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
let i = 1e7
|
||||||
|
while (i) do
|
||||||
|
i=i-1
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
let i = 10
|
let i = 10
|
||||||
let x = 1
|
let x = 1
|
||||||
|
let n = 1e1000000 * 1e1000000 * 1e1000000 * 1e1000000 * 1e1000000 * 1e1000000 * 1e1000000 * 1e1000000 * 1e1000000 * 1e1000000 * 1e1000000 * 1e1000000 * 1e1000000 * 1e1000000 * 1e1000000 * 1e1000000 * 1e1000000 * 1e1000000 * 1e1000000 * 1e1000000 * 1e1000000 * 1e1000000 * 1e1000000 * 1e1000000
|
||||||
while (i) do
|
while (i) do
|
||||||
x = x * 1e100000000
|
x = x*n
|
||||||
term.log(i=i-1)
|
term.log(i=i-1)
|
||||||
term.log(x)
|
|
||||||
Reference in New Issue
Block a user