From 426d9c9977489f7adba7f4b554e8466a47e520f1 Mon Sep 17 00:00:00 2001
From: Leo Tenenbaum
Date: Wed, 29 Jan 2020 11:37:25 -0500
Subject: made #foreign a part of the language
---
README.html | 31 +++++++++++------------
README.md | 3 ++-
build.sh | 17 ++++++-------
compatibility.c | 77 ---------------------------------------------------------
docs/00.html | 7 +++---
docs/01.html | 4 +--
eval.c | 2 +-
foreign.c | 4 +--
8 files changed, 31 insertions(+), 114 deletions(-)
delete mode 100644 compatibility.c
diff --git a/README.html b/README.html
index baa360d..e3ea45d 100644
--- a/README.html
+++ b/README.html
@@ -11,24 +11,24 @@ and there are almost definitely bugs right now.
I would recommend against using it for anything big or important.
Many parts of it may change in the future.
-toc
improves on C’s syntax (and semantics) in many ways,
+
toc
improves on C's syntax (and semantics) in many ways,
To declare x
as an integer and set it to 5,
you can do:
-x := 5; // Declare x and set x to 5 (infer type)
-x : int = 5; // Explicitly make the type int.
-x : int; x = 5; // Declare x as an integer, then set it to 5.
+x := 5; // Declare x and set x to 5 (infer type)
+x : int = 5; // Explicitly make the type int.
+x : int; x = 5; // Declare x as an integer, then set it to 5.
-toc
is statically typed and has many of C’s features, but
+
toc
is statically typed and has many of C's features, but
it is nearly as fast in theory.
See docs
for more information (in progress).
tests
has some test programs written in toc
.
-To compile the compiler on a Unix-y system, just run ./build.sh release
. You can supply a compiler by running CC=tcc ./build.sh release
, or build it in debug mode without the release
.
+To compile the compiler on a Unix-y system, just run ./build.sh release
. You can supply a compiler by running CC=tcc ./build.sh release
, or build it in debug mode without the release
. To disable compile time foreign function support (which you will need to do if you don't have ffcall/dl), prefix this with COMPILE_TIME_FOREIGN_FN_SUPPORT=no
.
On other systems, you can just compile main.c with a C compiler. toc
uses several C99 and a couple of C11 features, so it might not work on all compilers. But it does compile on quite a few, including clang
, gcc
, and tcc
. It can also be compiled as if it were C++, so, MSVC and g++
can also compile it (it does rely on implicit casting of void *
though). The outputted code should be C99-compliant.
@@ -37,11 +37,10 @@ it is nearly as fast in theory.
toc
compiles to C. Here are some reasons why:
-- Speed. C is one of the most performant programming languages out there. It also has compilers which are very good at optimizing (better than anything I could write).
+- Speed. C is one of the most performant programming languages out there. It also has compilers which are very good at optimizing (better than anything I could write).
- Portability. C is probably the most portable language. It has existed for >30 years and can run on practically anything. Furthermore, all major languages nowadays can call functions written in C.
-
toc
Compiler Source Code
@@ -54,15 +53,15 @@ it is nearly as fast in theory.
Build system
-toc
is set up as a unity build, meaning that there is only one translation unit. So, main.c
#include
s toc.c
, which #include
s all of toc
’s files.
+toc
is set up as a unity build, meaning that there is only one translation unit. So, main.c
#include
s toc.c
, which #include
s all of toc
's files.
Why?
-This improves compilation speeds (especially from scratch), since you don’t have to include headers a bunch of times for each translation unit. This is more of a problem in C++, where, for example, doing #include <map>
ends up turning into 25,000 lines after preprocessing. All of toc’s source code, which includes most of the C standard library, at the time of this writing (Dec 2019) is only 22,000 lines after preprocessing; imagine including all of that once for each translation unit which includes map
. It also obviates the need for fancy build systems like CMake.
+This improves compilation speeds (especially from scratch), since you don't have to include headers a bunch of times for each translation unit. This is more of a problem in C++, where, for example, doing #include <map>
ends up turning into 25,000 lines after preprocessing. All of toc's source code, which includes most of the C standard library, at the time of this writing (Dec 2019) is only 22,000 lines after preprocessing; imagine including all of that once for each translation unit which includes map
. It also obviates the need for fancy build systems like CMake.
New features
-Here are all the C99 features which toc
depends on (I might have forgotten some…):
+Here are all the C99 features which toc
depends on (I might have forgotten some...):
- Declare anywhere
@@ -71,15 +70,13 @@ it is nearly as fast in theory.
- Flexible array members
-
And here are all of its C11 features:
- Anonymous structures/unions
-max_align_t
- It can still compile without this, and will almost definitely work, but it won’t technically be standard-compliant
+max_align_t
- It can still compile without this, and will almost definitely work, but it won't technically be standard-compliant
-
More
See main.c
for a bit more information.
@@ -94,13 +91,13 @@ it is nearly as fast in theory.
Version | Description | Date |
0.0 | Initial version. | 2019 Dec 6 |
0.1 | Constant parameter inference. | 2019 Dec 15 |
+0.2 | Foreign functions and #include. | 2020 Jan 29 |
-
Report a bug
-If you find a bug, you can report it through GitHub’s issue tracker, or by emailing pommicket@gmail.com.
+If you find a bug, you can report it through GitHub's issue tracker, or by emailing pommicket@gmail.com.
-Just send me the toc
source code which results in the bug, and I’ll try to fix it.
+Just send me the toc
source code which results in the bug, and I'll try to fix it.
diff --git a/README.md b/README.md
index 2fa6838..f602920 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ See `docs` for more information (in progress).
`tests` has some test programs written in `toc`.
-To compile the compiler on a Unix-y system, just run `./build.sh release`. You can supply a compiler by running `CC=tcc ./build.sh release`, or build it in debug mode without the `release`.
+To compile the compiler on a Unix-y system, just run `./build.sh release`. You can supply a compiler by running `CC=tcc ./build.sh release`, or build it in debug mode without the `release`. To disable compile time foreign function support (which you will need to do if you don't have ffcall/dl), prefix this with `COMPILE_TIME_FOREIGN_FN_SUPPORT=no`.
On other systems, you can just compile main.c with a C compiler. `toc` uses several C99 and a couple of C11 features, so it might not work on all compilers. But it does compile on quite a few, including `clang`, `gcc`, and `tcc`. It can also be compiled as if it were C++, so, MSVC and `g++` can also compile it (it does rely on implicit casting of `void *` though). The *outputted* code should be C99-compliant.
@@ -82,6 +82,7 @@ Here are the major versions of `toc`.
Version | Description | Date |
0.0 | Initial version. | 2019 Dec 6 |
0.1 | Constant parameter inference. | 2019 Dec 15 |
+0.2 | Foreign functions and #include. | 2020 Jan 29 |
---
diff --git a/build.sh b/build.sh
index 6dadf63..6a415a6 100755
--- a/build.sh
+++ b/build.sh
@@ -21,22 +21,19 @@ else
WARNINGS=''
fi
-if [ "$1" = "" ]; then
- if [ "$COMPILE_TIME_FOREIGN_FN_SUPPORT" != "no" ]; then
- ADDITIONAL_FLAGS="$ADDITIONAL_FLAGS -DCOMPILE_TIME_FOREIGN_FN_SUPPORT=1 -lffcall -ldl"
- fi
+if [ "$COMPILE_TIME_FOREIGN_FN_SUPPORT" != "no" ]; then
+ ADDITIONAL_FLAGS="$ADDITIONAL_FLAGS -DCOMPILE_TIME_FOREIGN_FN_SUPPORT=1 -lffcall -ldl"
fi
-DEBUG_FLAGS="-O0 -no-pie -gdwarf-2 -pipe $WARNINGS -std=c11 -DTOC_DEBUG"
+
+DEBUG_FLAGS="-O0 $WARNINGS -std=c11 -DTOC_DEBUG"
+if [ "$CC" = "gcc" ]; then
+ DEBUG_FLAGS="$DEBUG_FLAGS -no-pie -gdwarf-2 -pipe"
+fi
RELEASE_FLAGS="-O3 -s -DNDEBUG $WARNINGS -std=c11"
if [ "$1" = "release" ]; then
FLAGS="$RELEASE_FLAGS $ADDITIONAL_FLAGS"
-
- COMMAND="$CC compatibility.c -Wall -Wextra -o compatibility"
- echo $COMMAND
- $COMMAND || exit 1
- FLAGS="$FLAGS $(./compatibility)"
else
FLAGS="$DEBUG_FLAGS $ADDITIONAL_FLAGS"
fi
diff --git a/compatibility.c b/compatibility.c
deleted file mode 100644
index 6a7c32c..0000000
--- a/compatibility.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
-This is free and unencumbered software released into the public domain.
-Anyone is free to copy, modify, publish, use, compile, sell, or
-distribute this software, either in source code form or as a compiled
-binary, for any purpose, commercial or non-commercial, and by any
-means.
-In jurisdictions that recognize copyright laws, the author or authors
-of this software dedicate any and all copyright interest in the
-software to the public domain. We make this dedication for the benefit
-of the public at large and to the detriment of our heirs and
-successors. We intend this dedication to be an overt act of
-relinquishment in perpetuity of all present and future rights to this
-software under copyright law.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-For more information, please refer to
-*/
-
-#include
-#include
-#include
-#include
-
-typedef float F32;
-typedef double F64;
-typedef uint32_t U32;
-typedef uint64_t U64;
-
-int main(void) {
- int *p;
- memset(&p, 0, sizeof p);
- if (p) {
- fprintf(stderr, "You cannot run toc. Sorry.\n");
- return EXIT_FAILURE;
- }
-
-
- FILE *f;
- f = tmpfile();
- /* endianness test */
- putc(0x12, f);
- putc(0x34, f);
- putc(0x56, f);
- putc(0x78, f);
-
- if (sizeof(float) != 4 || sizeof(double) != 8) {
- fprintf(stderr, "You may experience some problems with toc (sizeof(double) and sizeof(float) are strange).");
- goto unusual;
- } else {
- F32 flt = -12.3456f;
- fwrite(&flt, sizeof flt, 1, f);
- F64 dbl = -12.3456;
- fwrite(&dbl, sizeof dbl, 1, f);
- }
- fseek(f, 0L, SEEK_SET);
- U32 num;
- fread(&num, sizeof num, 1, f);
- if (num != 0x78563412) {
- /* not little endian */
- goto unusual;
- }
- U32 flt_rep;
- fread(&flt_rep, sizeof flt_rep, 1, f);
- if (flt_rep != 0xc1458794) goto unusual;
- U64 dbl_rep;
- fread(&dbl_rep, sizeof dbl_rep, 1, f);
- if (dbl_rep != 0xc028b0f27bb2fec5) goto unusual;
- return 0;
- unusual:
- printf("-DBINFILE_PORTABLE");
- return 0;
-}
diff --git a/docs/00.html b/docs/00.html
index b8c961c..cd0c352 100644
--- a/docs/00.html
+++ b/docs/00.html
@@ -30,7 +30,7 @@ x := 0.0;
when no type is specified, it defaults to an int
, whereas 0.0
defaults to a float
.
-Here are all of toc’s builtin types and their ranges of values:
+Here are all of toc's builtin types and their ranges of values:
int
- A 64-bit signed integer (always), -9223372036854775808 to 9223372036854775807
@@ -49,14 +49,13 @@ defaults to a float
.
char
- A character. The specific values are technically platform-dependent, but usually there are 256 of them.
-
At the moment, it is not technically guaranteed that f32
/float
is actually 32-bit and that f64
is actually 64-bit; they are platform dependent. Perhaps someday there will be a version of toc which does not compile to C, where that could be guaranteed.
To make declarations constant, use ::
instead of :
. e.g.
-x ::= 5+3;
+x ::= 5+3;
y :: float = 5.123;
-Here, “constant” means constant at compile time, not read-only as it does in C. One interesting thing about toc is that normal functions can run at compile time, so pretty much any expression is a valid initializer for a constant, e.g. doing x ::= some_function();
runs some_function
at compile time, not at run time.
+Here, "constant" means constant at compile time, not read-only as it does in C. One interesting thing about toc is that normal functions can run at compile time, so pretty much any expression is a valid initializer for a constant, e.g. doing x ::= some_function();
runs some_function
at compile time, not at run time.
diff --git a/docs/01.html b/docs/01.html
index 6dce358..633295b 100644
--- a/docs/01.html
+++ b/docs/01.html
@@ -7,7 +7,7 @@ main ::= fn() {
};
-It declares a constant, main
, which is a function with an empty body. Note that the syntax for declaring functions is the same as the syntax for declaring constants (it isn’t something like fn main() { ... }
).
+It declares a constant, main
, which is a function with an empty body. Note that the syntax for declaring functions is the same as the syntax for declaring constants (it isn't something like fn main() { ... }
).
Assuming you have compiled the compiler (see README.md
for instructions about that), you can compile it with
@@ -15,4 +15,4 @@ main ::= fn() {
toc <your filename>
-You will get a file called out.c
, which you can then put through your C compiler to get an executable file which does nothing. Congratulations! You’ve written your first toc program.
+You will get a file called out.c
, which you can then put through your C compiler to get an executable file which does nothing. Congratulations! You've written your first toc program.
diff --git a/eval.c b/eval.c
index 8019f4f..1eb7c1e 100644
--- a/eval.c
+++ b/eval.c
@@ -735,7 +735,7 @@ static void *eval_ptr_to_struct_field(Evaluator *ev, Expression *dot_expr) {
struc_data = struc.ptr;
if (struc_data == NULL) {
err_print(dot_expr->where, "Attempt to dereference NULL pointer.");
- return false;
+ return NULL;
}
} else {
struc_data = struc.struc;
diff --git a/foreign.c b/foreign.c
index b55a908..48d8d4a 100644
--- a/foreign.c
+++ b/foreign.c
@@ -312,8 +312,8 @@ static bool foreign_call(ForeignFnManager *ffmgr, FnExpr *fn, Type *fn_type, Val
static void ffmgr_free(ForeignFnManager *ffmgr) {
arr_foreach(ffmgr->libs_loaded.slots, StrHashTableSlotPtr, slotp) {
if (*slotp) {
- Library lib = *(Library *)((*slotp)->data);
- dlclose(lib.handle);
+ Library *lib = (void *)((*slotp)->data);
+ dlclose(lib->handle);
}
}
str_hash_table_free(&ffmgr->libs_loaded);
--
cgit v1.2.3