Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
23 changes: 0 additions & 23 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
.sconsign.dblite
.sconf_temp/
config.log
*.inc
*.o
*.os
Expand All @@ -11,35 +9,14 @@ config.log
*.dylib
*.dll
*.gc*
*.pyc
*.neonx
*.neond
bin/
errors.txt
config.py
test_grammar

external/IntelRDFPMathLib20U1/
external/utf8/
external/libffi-3.2.1/
external/PDCurses-3.4/
external/easysid-version-1.0/
external/hash-library/
external/pcre2-10.10/
external/curl-7.41.0/
external/sqlite-amalgamation-3080803/
external/zlib-1.2.8/
external/bzip2-1.0.6/
external/xz-5.2.1/
external/minijson_writer-master/
external/NaturalDocs/
external/pyparsing-2.0.3/
external/minizip11/
external/SDL2-2.0.3/
external/libsodium-1.0.5/
external/libressl-2.2.4/

external/etc
external/include
external/lib
external/share
1 change: 0 additions & 1 deletion .neonpath

This file was deleted.

6 changes: 0 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
language: cpp
os:
- linux
- osx
compiler:
- gcc
- clang
before_install:
- which scons || brew install scons
script: scons
sudo: false
28 changes: 10 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ False

This happens because `0.2` cannot be repesented exactly in binary floating point.

To resolve this problem, Neon uses the [decimal128](https://en.wikipedia.org/wiki/Decimal128_floating-point_format) floating point type, which matches the base 10 that humans use to read and write numbers.
To resolve this problem, Neon uses the [decimal64](https://en.wikipedia.org/wiki/Decimal64_floating-point_format) floating point type, which matches the base 10 that humans use to read and write numbers.

<a name="integer_division"></a>
### Writing division expressions such as `5 / 2` and not expecting integer division
Expand All @@ -92,7 +92,7 @@ Beginners rightly assume that `c` will be `2.5` as the result of the division.
However, the C language definition states that `/` will be *integer* division if both operands are integers.
So, the result in `c` is `2`.

To resolve this problem, the only number type in Neon is decimal128 floating point (called `Number`).
To resolve this problem, the only number type in Neon is decimal64 floating point (called `Number`).
In contexts such as array indexing where integers are expected, values are checked for the presence of a fractional part before trying to use them.

<a name="assignment_equals"></a>
Expand All @@ -111,15 +111,11 @@ In many common systems languages (eg. C, C++, Java, C#), a pointer may hold a "n

To resolve this problem, Neon introduces the idea of a "valid" pointer. A valid pointer is one that has been checked against `NIL` (the null reference) using a special form of the `IF` statement. The resulting valid pointer can be dereferenced without causing a null pointer exception.

TYPE Node IS RECORD
value: String
END RECORD

FUNCTION output(node: POINTER TO Node)
IF VALID node AS p THEN
print(p->value)
END IF
END FUNCTION
VAR node: POINTER TO Node

IF VALID p := node THEN
print(p.value)
END IF

<a name="empty_loop"></a>
### Unintended empty loop with `while (condition);`
Expand All @@ -130,20 +126,16 @@ In C and derived languages, sometimes a loop or conditional is mistakenly writte
while (x < 5);
{
printf("%d\n", x);
x++;
}
```

The trailing `;` on the `while` statement is in fact an empty loop body and the loop is an infinite loop.

To resolve this problem, Neon requires an explicitly terminated block in every compound statement:

VAR x: Number := 0

WHILE x < 5 DO
print("\(x)")
INC x
END WHILE
WHILE x < 5
print(x)
END

<a name="logical_alternative"></a>
### Writing `if a == b or c` (in Python) to test whether `a` is equal to either `b` or `c`
Expand Down
80 changes: 80 additions & 0 deletions SConscript-libffi
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import os
import sys
import tarfile

def find_tool(name):
justname = os.path.basename(name)
for p in env["ENV"]["PATH"].split(";"):
fn = os.path.join(p, justname)
if os.access(fn, os.F_OK):
return fn
fn = os.path.join(p, name)
if os.access(fn, os.F_OK):
return fn
print >>sys.stderr, "could not find tool:", name
sys.exit(1)

def subs(target, source, env):
with open(target[0].path, "w") as outf, open(source[0].path) as inf:
outf.write(inf.read()
.replace("@VERSION@", "3.2.1")
.replace("@TARGET@", "X86_WIN64")
.replace("@HAVE_LONG_DOUBLE@", "HAVE_LONG_DOUBLE")
.replace("@HAVE_LONG_DOUBLE_VARIANT@", "HAVE_LONG_DOUBLE_VARIANT")
.replace("@FFI_EXEC_TRAMPOLINE_TABLE@", "FFI_EXEC_TRAMPOLINE_TABLE")
)

def fix_target(target, source, env):
with open(target[0].path, "w") as outf, open(source[0].path) as inf:
for s in inf:
if s.startswith("#define FFI_TARGET_HAS_COMPLEX_TYPE"):
s = "//" + s
outf.write(s)

def sub_config(target, source, env):
with open(target[0].path, "w") as outf, open(source[0].path) as inf:
for s in inf:
if s.startswith("#undef"):
if s.split()[1] in [
"HAVE_MEMCPY",
"FFI_NO_RAW_API",
]:
s = "#define {} 1".format(s.split()[1])
outf.write(s)

def remove_short(target, source, env):
with open(target[0].path, "w") as outf, open(source[0].path) as inf:
outf.write(inf.read().replace("SHORT", ""))

Import("env")

if sys.platform == "win32":
env.Command("external/libffi-3.2.1/include/ffi.h.in", "external/libffi-3.2.1.tar.gz", lambda target, source, env: tarfile.open(source[0].path).extractall("external"))
env.Append(CPPDEFINES=["FFI_BUILDING"])
ffienv = env.Clone()
ffienv.Append(CPPPATH=["external/libffi-3.2.1/x86-win64/include"])
ffi_h = ffienv.Command("external/libffi-3.2.1/x86-win64/include/ffi.h", "external/libffi-3.2.1/include/ffi.h.in", subs)
ffitarget_h = ffienv.Command("external/libffi-3.2.1/x86-win64/include/ffitarget.h", "external/libffi-3.2.1/src/x86/ffitarget.h", fix_target)
fficommon_h = ffienv.Command("external/libffi-3.2.1/x86-win64/include/ffi_common.h", "external/libffi-3.2.1/include/ffi_common.h", Copy("$TARGET", "$SOURCE"))
fficonfig_h = ffienv.Command("external/libffi-3.2.1/x86-win64/include/fficonfig.h", "external/libffi-3.2.1/fficonfig.h.in", sub_config)
win64_p = ffienv.Command("external/libffi-3.2.1/x86-win64/win64.p", "external/libffi-3.2.1/src/x86/win64.S", "cl /EP /I external/libffi-3.2.1/x86-win64/include $SOURCE >$TARGET")
win64_asm = ffienv.Command("external/libffi-3.2.1/x86-win64/win62.asm", win64_p, remove_short)
objects = [
ffienv.Object("external/libffi-3.2.1/x86-win64/closures.obj", "external/libffi-3.2.1/src/closures.c"),
ffienv.Object("external/libffi-3.2.1/x86-win64/ffi.obj", "external/libffi-3.2.1/src/x86/ffi.c"),
ffienv.Object("external/libffi-3.2.1/x86-win64/prep_cif.obj", "external/libffi-3.2.1/src/prep_cif.c"),
ffienv.Object("external/libffi-3.2.1/x86-win64/types.obj", "external/libffi-3.2.1/src/types.c"),
]
for o in objects:
ffienv.Depends(o, [ffi_h, ffitarget_h, fficommon_h, fficonfig_h])
libffi = ffienv.Library("external/libffi-3.2.1/x86-win64/libffi.lib", objects + [
ffienv.Command("external/libffi-3.2.1/x86-win64/win64.obj", win64_asm, "\"{}\" /c /Cx /Fo$TARGET $SOURCE".format(find_tool("x86_amd64/ml64.exe"))),
])
ffienv.Install("external/lib/libffi-3.2.1/include/", [ffi_h, ffitarget_h, fficommon_h, fficonfig_h])
libffi = ffienv.Install("external/lib/", libffi)
else:
env.Command("external/libffi-3.2.1/configure", "external/libffi-3.2.1.tar.gz", lambda target, source, env: tarfile.open(source[0].path).extractall("external"))
env.Command("external/libffi-3.2.1/Makefile", "external/libffi-3.2.1/configure", "cd external/libffi-3.2.1 && ./configure --prefix=`pwd`/..")
libffi = env.Command("external/lib/libffi.a", "external/libffi-3.2.1/Makefile", "cd external/libffi-3.2.1 && make && make install")

Return(["libffi"])
Loading