summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyle Gunger <kgunger12@gmail.com>2021-04-30 14:06:58 -0400
committerKyle Gunger <kgunger12@gmail.com>2021-04-30 14:06:58 -0400
commitc625ed1cfe7f7ea4ab2a75a8a0a6a6772f86431c (patch)
tree55aab8a27a6cd3b0a979002afa6899a4bda94b74
parent60f7c4f7272079e635010e464d8ce3a3a427f97f (diff)
Destroy my own code by using goto
-rwxr-xr-xgobuild.sh1
-rw-r--r--out.tnp1
-rw-r--r--qualifiers.txt71
-rw-r--r--small-tests/base.tnsl (renamed from base.tnsl)0
-rw-r--r--small-tests/examp.tnsl (renamed from examp.tnsl)0
-rw-r--r--small-tests/out.tnt1
-rw-r--r--small-tests/test.tnsl13
-rw-r--r--spec/compiler/compiler.txt9
-rw-r--r--spec/compiler/pre-processor.txt6
-rw-r--r--spec/iex/iex-spec.txt128
-rw-r--r--spec/libts.txt93
-rw-r--r--spec/spec.txt99
-rw-r--r--src/main.go2
-rw-r--r--src/tparse/resolver.go24
-rw-r--r--src/tparse/tree-list.go45
-rw-r--r--src/tparse/tree-statement.go55
-rw-r--r--src/tparse/tree-value.go130
-rw-r--r--src/tparse/tree.go15
-rw-r--r--src/tparse/type.go5
-rw-r--r--tests/block-test.tnsl13
-rw-r--r--tests/parameter-test.tnsl2
-rwxr-xr-xtests/run-tests.sh18
-rw-r--r--tests/statement-test.tnsl6
23 files changed, 603 insertions, 134 deletions
diff --git a/gobuild.sh b/gobuild.sh
index 684fd52..67b7acf 100755
--- a/gobuild.sh
+++ b/gobuild.sh
@@ -4,4 +4,5 @@ SRCDIR=$(pwd)
export GOPATH="$GOPATH:$SRCDIR"
+go env -w GO111MODULE=off
go build -o build/parse src/main.go
diff --git a/out.tnp b/out.tnp
deleted file mode 100644
index bc7c455..0000000
--- a/out.tnp
+++ /dev/null
@@ -1 +0,0 @@
-[{0 : 12 0} {6 import 12 1} {4 'what/what.tnsl' 12 8} {8 a 12 25} {0 : 14 0} {6 import 14 1} {4 "what/what.tnsl" 14 8} {0 ; 19 0} {5 int 19 1} {8 s 19 5} {3 = 19 7} {4 3 19 9} {0 ; 21 0} {5 byte 21 1} {8 bitbyte 21 6} {3 = 21 14} {3 . 21 16} {4 2 21 17} {2 /; 28 0} {0 ; 30 2} {5 int 30 3} {8 d 30 7} {3 = 30 9} {4 1 30 11} {0 ; 32 2} {8 s 32 3} {3 = 32 5} {8 d 32 7} {2 ;/ 34 0} {2 /; 43 0} {8 main 43 2} {2 ( 43 7} {2 { 43 8} {2 } 43 9} {8 string 43 10} {8 str 43 17} {2 ) 43 20} {2 [ 43 22} {5 int 43 23} {2 ] 43 26} {0 ; 51 2} {5 int 51 3} {8 i 51 7} {3 = 51 9} {4 1 51 11} {0 ; 52 2} {3 ~ 52 3} {5 int 52 4} {8 j 52 8} {3 ~= 52 10} {8 i 52 13} {8 j 53 2} {3 ~ 53 3} {3 = 53 5} {4 2 53 7} {2 /; 58 2} {7 loop 58 4} {2 [ 58 9} {8 i 58 10} {3 !== 58 11} {4 1 58 14} {2 ] 58 16} {0 ; 60 4} {8 i 60 6} {3 = 60 8} {4 1 60 10} {2 ;/ 61 2} {2 ;/ 63 0} {0 ; 68 0} {7 struct 68 1} {2 [ 68 8} {8 s1 68 9} {2 ] 68 11} {2 { 68 13} {8 string 68 14} {8 Name 68 21} {1 , 68 25} {8 string 68 27} {8 Message 68 34} {3 = 68 42} {4 "Default message (c-style strings)" 68 44} {2 } 68 79} {0 ; 71 0} {7 struct 71 1} {2 [ 71 8} {8 s1 71 9} {2 ] 71 11} {2 { 71 13} {8 string 72 4} {8 Name 72 11} {1 , 72 15} {8 string 73 4} {8 Message 73 11} {3 = 73 19} {4 "Default message (c-style strings)" 73 21} {2 } 74 0} {0 ; 77 0} {8 s1 77 1} {8 a 77 4} {3 = 77 6} {2 { 77 8} {2 } 77 9} {0 ; 79 0} {8 s1 79 1} {8 a 79 4} {2 { 79 5} {2 } 79 6} {0 ; 80 0} {8 a 80 1} {3 . 80 2} {8 Name 80 3} {3 = 80 8} {4 "Kyle Gunger" 80 10} {0 ; 82 0} {3 ~ 82 1} {8 s1 82 2} {8 b 82 5} {3 = 82 7} {3 ~ 82 9} {8 a 82 10} {0 ; 83 0} {8 b 83 1} {3 ~ 83 2} {3 . 83 3} {8 Name 83 4} {0 ; 86 0} {8 s1 86 1} {8 c 86 4} {3 = 86 6} {2 { 86 8} {4 "" 86 9} {1 , 86 11} {4 "" 86 13} {2 } 86 15} {0 ; 90 0} {8 s1 90 1} {8 d 90 4} {2 { 90 5} {8 Message 91 4} {3 = 91 12} {4 "Message" 91 14} {1 , 91 23} {8 Name 92 4} {3 = 92 9} {4 "Name" 92 11} {2 } 93 0} {0 ; 99 0} {2 { 99 1} {2 } 99 2} {5 int 99 3} {8 a 99 7} {3 = 99 9} {2 { 99 11} {4 1, 100 2} {4 2, 100 6} {4 3, 100 10} {4 4 100 14} {2 } 101 0} {0 ; 104 0} {2 { 104 1} {2 } 104 2} {5 int 104 3} {8 a 104 7} {2 { 104 8} {4 1, 105 2} {4 2, 105 6} {4 3, 105 10} {4 4 105 14} {2 } 106 0} {2 /; 110 0} {8 s1 110 2} {2 [ 110 5} {8 s1 110 6} {2 ] 110 8} {8 return 112 2} {8 new 112 9} {8 s1 112 13} {2 { 112 15} {4 "Kyle" 112 16} {1 , 112 22} {4 "TNSL Creator" 112 24} {2 } 112 38} {2 ;/ 113 0} {2 /; 115 0} {7 if 115 3} {2 ( 115 6} {8 i 115 7} {3 == 115 9} {4 3 115 12} {2 ) 115 14} {2 ;; 118 0} {7 else 118 2} {2 ;/ 120 0} {2 /; 122 0} {7 switch 122 3} {2 ( 122 10} {8 i 122 11} {2 ) 122 12} {0 ; 124 2} {5 int 124 3} {8 t 124 7} {3 = 124 9} {4 0 124 11} {2 /; 127 2} {7 case 127 4} {4 1 127 9} {0 ; 128 4} {8 i 128 5} {3 = 128 7} {4 0 128 9} {0 ; 129 4} {8 t 129 5} {3 = 129 7} {4 2 129 9} {0 ; 130 4} {7 break 130 5} {2 ;; 132 2} {7 case 132 4} {4 2 132 9} {0 ; 133 4} {8 i 133 5} {3 = 133 7} {4 1 133 9} {0 ; 134 4} {8 t 134 5} {3 = 134 7} {4 2 134 9} {0 ; 135 4} {7 break 135 5} {2 ;; 137 2} {7 default 137 4} {0 ; 138 4} {8 i 138 5} {3 = 138 7} {4 3 138 9} {0 ; 139 4} {7 break 139 5} {2 ;/ 140 2} {2 /; 143 2} {7 if 143 5} {2 [ 143 8} {8 t 143 9} {3 == 143 11} {4 2 143 14} {2 ] 143 16} {0 ; 144 4} {8 i 144 5} {3 = 144 7} {8 t 144 9} {3 - 144 11} {8 i 144 13} {2 ;; 146 2} {7 else 146 4} {7 if 146 9} {2 [ 146 12} {8 t 146 13} {3 == 146 14} {4 3 146 16} {2 ] 146 18} {0 ; 147 4} {8 i 147 5} {3 = 147 7} {8 t 147 9} {3 + 147 10} {8 i 147 11} {2 ;/ 148 2} {2 /; 151 2} {7 case 151 4} {4 1 151 9} {0 ; 152 4} {8 i 152 5} {3 = 152 7} {4 4 152 9} {2 ;/ 153 2} {2 ;/ 154 0} {0 ; 158 0} {7 struct 158 2} {2 [ 158 9} {8 gen 158 10} {2 ] 158 13} {2 ( 158 15} {7 type 158 16} {8 T 158 21} {2 ) 158 22} {2 { 158 24} {8 T 159 2} {8 i 159 4} {2 } 160 0} {0 ; 163 0} {8 gen 163 1} {2 ( 163 4} {5 int 163 5} {2 ) 163 8} {8 j 163 10} {2 { 163 11} {4 2 163 12} {2 } 163 14} {0 ; 166 0} {2 { 166 1} {2 } 166 2} {8 gen 166 3} {2 ( 166 6} {8 gen 166 7} {2 ( 166 10} {5 int 166 11} {2 ) 166 14} {2 ) 166 15} {8 j 166 17} {2 { 166 18} {2 { 167 2} {2 { 167 3} {4 1 167 4} {2 } 167 6} {2 } 167 7} {1 , 167 8} {2 { 168 2} {2 { 168 3} {4 2 168 4} {2 } 168 6} {2 } 168 7} {1 , 168 8} {2 { 169 2} {2 { 169 3} {4 3 169 4} {2 } 169 6} {2 } 169 7} {2 } 170 0}] \ No newline at end of file
diff --git a/qualifiers.txt b/qualifiers.txt
new file mode 100644
index 0000000..835a5f5
--- /dev/null
+++ b/qualifiers.txt
@@ -0,0 +1,71 @@
+block qualifier list:
+
+interface**
+enum**
+loop
+match
+if
+else
+method*
+override*
+raw
+inline
+export
+module
+case
+default
+operator*
+
+
+
+structure of blocks:
+
+(block start)
+ interface (defword)
+ enum (defword) (return type list)
+
+ loop (bool params) (loop rets)
+ if (bool params)
+ else
+ if (bool params)***
+
+ match (match params) (case blocks)
+ case (case params)
+ default
+
+ override***
+ method (defword) (function params) (function rets)
+ operator <unary operator> (ret)
+ operator <binary operator> (param) (ret)
+
+ export***
+ module (defword)
+
+ inline***
+ raw***
+ (defword) (function params) (function rets)
+(block end)
+
+
+
+structure of statements:
+
+(type) (definition list)
+(value)
+(keyword) (parameters if required)
+
+
+
+keyword statements:
+
+delete (list of defwords)*
+struct (defword) (struct params)*
+continue
+break
+label (defword)
+goto (defword)
+asm (defstring)
+
+* - type extension
+** - advanced type extension
+*** - optional modifier
diff --git a/base.tnsl b/small-tests/base.tnsl
index f291cf3..f291cf3 100644
--- a/base.tnsl
+++ b/small-tests/base.tnsl
diff --git a/examp.tnsl b/small-tests/examp.tnsl
index 0c32f3f..0c32f3f 100644
--- a/examp.tnsl
+++ b/small-tests/examp.tnsl
diff --git a/small-tests/out.tnt b/small-tests/out.tnt
new file mode 100644
index 0000000..9f77b4b
--- /dev/null
+++ b/small-tests/out.tnt
@@ -0,0 +1 @@
+{{9 test.tnsl 0 0} [{{10 block 0 0} [{{10 block 0 0} [{{11 ; 0 0} []} {{11 ; 0 0} []}]} {{10 block 0 0} [{{11 ; 0 0} []} {{11 ; 0 0} []}]} {{11 ; 0 0} []} {{11 ; 0 0} []}]} {{11 ; 0 0} []}]}
diff --git a/small-tests/test.tnsl b/small-tests/test.tnsl
new file mode 100644
index 0000000..f7c030c
--- /dev/null
+++ b/small-tests/test.tnsl
@@ -0,0 +1,13 @@
+/;
+ /;
+ ;
+ ;
+ ;;
+ ;
+ ;
+ ;/
+ ;
+ ;
+;/
+
+; thing \ No newline at end of file
diff --git a/spec/compiler/compiler.txt b/spec/compiler/compiler.txt
index dbc64c0..df7a591 100644
--- a/spec/compiler/compiler.txt
+++ b/spec/compiler/compiler.txt
@@ -10,9 +10,14 @@ in their own file.
2) Validation
- 2a) The expander - expands pre-processor commands and macrosoperations
+ 2a) The expander - expands pre-processor commands and macro operations
2b) The validator - checks all requirements for all functions and expressions are valid
3) Translation
- 3a) ??? \ No newline at end of file
+ 3a) Variable resolver - chooses and creates an internal model of where variables are on the stack, as well as calling conventions for functions
+ 3b) Type translator - places and translates types (internal and external)
+ 3c) Container resolver - checks container (elf, exe, dll, app, out, etc.) and decides how to map the types for future linking
+ 3d) Final translation - translates all logic and expressions into native binary code
+ 3e) Optimization
+ 3f) Container Writer - writes the final output of the previous steps into the specified container
diff --git a/spec/compiler/pre-processor.txt b/spec/compiler/pre-processor.txt
index 3203ff8..8297e7d 100644
--- a/spec/compiler/pre-processor.txt
+++ b/spec/compiler/pre-processor.txt
@@ -2,4 +2,8 @@ A set of components in the compiler (all before the translator) which expand,
resolve, and validate pre-processor directives into code which can be compiled
Consists of the resolver in the parsor.
-The expander and part of the indexer in the validator. \ No newline at end of file
+The expander and part of the indexer in the validator.
+
+Special (compiler specififc) definitions can be added with _<compiler>_<variable name>
+
+E.X. if the official implementation wanted to provide the exact time of the compilation, it could use _TNSLC_TIME_NOW for instance \ No newline at end of file
diff --git a/spec/iex/iex-spec.txt b/spec/iex/iex-spec.txt
new file mode 100644
index 0000000..6979cfc
--- /dev/null
+++ b/spec/iex/iex-spec.txt
@@ -0,0 +1,128 @@
+This is the IEX file specification.
+
+Document version (semver): 0.0.1
+Main Author: Kyle Gunger
+
+License: Apache 2.0
+
+----------------------------------
+
+Contents:
+
+Organization
+
+----------------------------------
+
+Organization
+
+Magic number starts the file "IEX" or 0x49 0x45 0x58
+
+The header of the file can be represented as such
+
+;struct IEX_HEAD {
+ raw {3}char # Always "IEX"
+ magic,
+
+ {}char
+ name,
+ arch,
+ os,
+
+ uint8 # Version info
+ major,
+ minor,
+ patch,
+ # OS abi info
+ os_major,
+ os_minor,
+ os_patch,
+
+ bool # Tells loader that the file holds a main function
+ can_execute,
+
+ ~void ({}{}char args) [int]
+ # Address of main in file
+ start_addr,
+
+ {}IEX_SECTION
+ sections,
+
+ {}IEX_LIB
+ dependencies,
+
+ IEX_MODULE
+ self
+}
+
+a section is defined as
+
+;struct IEX_SECTION {
+ {}char
+ name,
+
+ uint8 # Denotes dependency, symbol table, data, bss, text, etc.
+ type,
+
+ ~void # Points to start and end of section
+ start,
+ end
+}
+
+;struct IEX_LIB {
+ {}char
+ name,
+
+ uint8 # Version info
+ major,
+ minor,
+ patch
+}
+
+;struct IEX_MODULE {
+ {}char
+ name,
+
+ {}IEX_FUNCTION
+ func,
+
+ {}IEX_TYPE
+ types,
+
+ {}IEX_MODULE
+ sub
+}
+
+;struct IEX_FUNCTION {
+ {}char
+ name,
+
+ uint32
+ overload,
+ bytes_in,
+ bytes_out,
+
+ ~void
+ addr
+}
+
+;struct IEX_TYPE {
+ {}char
+ name,
+
+ bool
+ raw_struct,
+ interface,
+ dynamic,
+
+ uint32
+ size,
+
+ {}IEX_FUNCTION
+ methods,
+
+ {}IEX_TYPE
+ supers,
+
+ ~void
+ addr
+}
diff --git a/spec/libts.txt b/spec/libts.txt
index e69de29..e31d59d 100644
--- a/spec/libts.txt
+++ b/spec/libts.txt
@@ -0,0 +1,93 @@
+This is the LIBTS specification, a document related to the definition of the TNSL language,
+meta-language, it's usage, and where it's standard libraries may be ported.
+
+Document version (semver): 0.0.1
+Main Author: Kyle Gunger
+
+License: Apache 2.0
+
+----------------------------------
+
+Contents:
+
+Part 1 -- About the Library
+ 1.1: libts and TNSL
+ 1.2: Short overview
+
+Part 2 -- Library Features
+ 2.1: Bitwise operations
+ 2.2: Standard algorithms
+ 2.3: Continer structs
+ 2.4: Standard abstractions
+ 2.5: Time related APIs
+ 2.6: Method resolution
+
+----------------------------------
+
+Part 1: About the Library
+
+----------------------------------
+
+Section 1: libts and TNSL
+
+ libts or the TNSL standard library is a library to be found on almost all systems containing
+ a TNSL implimentation. The library contains both common APIs which ease common programming
+ feats as well as core program logic for the more high-level features of TNSL. TNSL can
+ indeed run without a libts, however doing so limits many parts of the language to the "raw"
+ variants. These limited features include structs, types, and interfaces primarially.
+
+ libts contains a standard method resolution algorithm such that method calls can be resolved
+ on runtime for the high level dynamic type system.
+
+----------------------------------
+
+Section 2: Short overview
+
+ The library contains many standard algoritims and abstractions found in other languages such
+ as C, as well as helpers for these containers.
+
+
+----------------------------------
+
+Part 2: Library Features
+
+----------------------------------
+
+Section 1: Bitwise Operations
+
+----------------------------------
+
+Section 2: Standard algorithms
+
+----------------------------------
+
+Section 3: Continer structs
+
+----------------------------------
+
+Section 4: Standard abstractions
+
+----------------------------------
+
+Section 5: Time related APIs
+
+ Time is important for any program, and libts provides an interface through which to query
+ the operating system for it. libts also provides conversion, projection, and timing features
+ so that programs can make use of user inputs relating to time. If bugs in the time projection
+ of the library, they will be fixed. No reguard to existing data should be given, accuracy is
+ the goal above breakage.
+
+ That being said, the library should attempt to work around erronious data in a way that
+ provides an alternative date if the data is in a good format but pointing to a non-existant
+ date. An error code will still be thrown in these cases, but indicating that the date does
+ not exist, not that the input was complete garbage. Programs may catch errors in any way
+ they choose.
+
+----------------------------------
+
+Section 6: Method resolution
+
+ As previously stated, the library performs method resolution for calls on high-level types.
+ In an iex file, this is done by finding the associated IEX_TYPE of the object and following
+ along the "supers" array and checking with the "methods" arrays until the IEX_TYPE contains
+ a definition for the method called which fits the caller's arguments. \ No newline at end of file
diff --git a/spec/spec.txt b/spec/spec.txt
index 033bb32..4086d3c 100644
--- a/spec/spec.txt
+++ b/spec/spec.txt
@@ -87,7 +87,7 @@ Each file may contain 0 or more of the following:
6) Module blocks
-Code blocks are the only blocks which may contain statements (1.3)
+Code blocks and method blocks are the only blocks which may contain statements (1.3) and logical blocks.
----------------------------------
@@ -321,13 +321,19 @@ Statements make up the actual "doing" part of TNSL
1) Literal values
Literal numbers start with a decimal number, and can contain up to one non-number element:
- 0b1001 - valid
0 - valid
0.2341 - valid
120000 - valid
.34567 - invalid
- 0
+ 0asd...kj - invalid
+
+ Special bases:
+
+ 0b1001 - valid (binary)
+ 0o0127 - valid (octal)
+ 0xABCD - valid (hex)
+ 0BZZZZ - valid (base 64)
These rules will be ammended and are mostly for ease of parsing in the first version of the language.
@@ -344,14 +350,24 @@ Statements make up the actual "doing" part of TNSL
" - invalid
Literal characters use '' and either an escape character or a single character/code point between them
-
+ ' ' - valid
+ '\u2000' - valid
+ '\\' - valid
+ '\'' - valid
+
+ invalid:
+ '\u200220202asdasdaw qwe '
+ '\\asd asd '
+ 'ab'
+ '\'
+ '
2) Call with a return
calling a function is as simple as naming a block of code and then calling it with parentheses
# Define
- /; add ()
+ /; add
;/
# Call (not expression)
@@ -403,8 +419,7 @@ Statements make up the actual "doing" part of TNSL
1.4: Types
TNSL's type system consists of built-in types, user interfaces, and user structs.
-The built-in types are always on the stack, while user types can be on the stack, on the heap,
-or somewhere in between.
+The built-in types are always on the stack, while user types can be on the stack or the heap.
1.4.1: Built-in types
Built-in types are meant to be portable so that tnsl can be backported to whatever system one may want.
@@ -453,20 +468,17 @@ or somewhere in between.
uint64 - 64 bit unsigned int
float64 - 64 bit floating point
- simd (NICE):
- not really sure how these work yet. I'll get back to you
+ vect (NICE):
+ vector, simd, etc. not really sure how these work yet. I'll get back to you
size 128 (NICE):
int128
uint128
float128
- comp128 - complex 128 bit (2 64 bit floats in a trenchcoat)
1.4.2: User defined types (stack)
Any structs defined not using pointers are automatically allocated on the stack.
- The meta type is really a pointer, and so structs using it will not be completely on
- the stack.
Structs are normally alligned to byte boundaries
@@ -474,11 +486,11 @@ or somewhere in between.
Defining a struct can be done as follows:
- ;struct <struct name> ( <optional inputs> ) { <list of members (may use inputs)> }
+ ;struct <struct name> (<list of inputs (makes this a dynamic type)>) { <list of members (may use inputs)> }
e.g.
- ;struct Vector2 {x, y int32}
+ ;struct Vector2 {int32 x, y}
Creating a variable from the struct can be done in two ways:
@@ -501,14 +513,14 @@ or somewhere in between.
method block example using operator
- /; method ~Vector2
+ /; method Vector2
- /; operator + (v ~Vector2)
+ /; operator + (~Vector2 v)
;self.x += `v.x
;self.y += `v.y
;/
- /; dot (v ~Vector2) [int32]
+ /; dot (~Vector2 v) [int32]
;return self.x * `v.x + self.y * `v.y
;/
@@ -605,12 +617,12 @@ and how functions are first-class in TNSL
Anonymous blocks can be written only as scope, or with inputs and outputs for function calls.
- /; call_func (to_call void(int32)[int32]) [int32]
+ /; call_func (void(int32)[int32] to_call) [int32]
;return to_call(5)
;/
/; provide_anon () [int32]
- ;return call_func(/; (a int32) [int32]
+ ;return call_func(/; (int32 a) [int32]
;return a + 1
;/)
;/
@@ -866,4 +878,51 @@ Augmented boolean operators (a !<op> b) = !(a <op> b)
>== - Same as !<
-<== - Same as !> \ No newline at end of file
+<== - Same as !>
+
+----------------------------------
+
+Appendix C: Memory control (and speed) with each type of struct
+
+Each type of user-definable type or struct or interface grants
+it's own level of memory control. These (and their ramifications) are
+listed here from low to high.
+
+---
+
+High level, low control structs (dynamic structs) are created when using
+the parameters for structs/types. They allow variable length which can
+house different information at the cost of speed, memory, and control.
+
+These are the only type of structs which can house other dynamic structs.
+Dynamic structs can only be passes by reference due to undefined size at
+compilation.
+
+---
+
+Medium level, medium control structs (type structs) are created normaly
+through the struct keyword without parameters. These structs are fixed
+length, but the compiler encodes extra info into them. This means they
+get method resolution and override checks which may reduce speed of the
+application.
+
+---
+
+Low level, high control structs (raw structs) are created using the "raw"
+keyword before the "struct" keyword. There are no frills, and method
+resolution is not performed for these structs. These structs may not
+extend or be extended. They may, however, implement interfaces. They
+perform as a "what you see is what you get" kind of memory model. They
+may not use parameters, and all internal types must be consistant length
+(no dynamic structs or dynamic type identifiers).
+
+---
+
+To summerize:
+All these structs can encode the same info, but as you get lower to
+the system, you get the bonus of speed and control while losing higher
+level functions provided by the language.
+
+This shouldn't matter much to most programmers unless they are doing
+embedded development, systems programming, or firmware programming,
+but it is still a consideration to make for time-sensitive applications. \ No newline at end of file
diff --git a/src/main.go b/src/main.go
index c74d0cb..e6efcd9 100644
--- a/src/main.go
+++ b/src/main.go
@@ -37,7 +37,7 @@ func main() {
tokens := tparse.TokenizeFile(*inputFile)
tree := tparse.MakeTree(&tokens, *inputFile)
- fd.WriteString(fmt.Sprint(tree))
+ fd.WriteString(fmt.Sprint(tree) + "\n")
fd.Close()
}
diff --git a/src/tparse/resolver.go b/src/tparse/resolver.go
deleted file mode 100644
index 5267887..0000000
--- a/src/tparse/resolver.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- Copyright 2020 Kyle Gunger
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-*/
-
-package tparse
-
-//TODO: Everything
-
-/*
- This file is support code to include other files when asked, and represents the most important part of the pre-processor
- Maybe we will do this when writing the native compiler though
-*/
diff --git a/src/tparse/tree-list.go b/src/tparse/tree-list.go
index 78e45a8..843ca9b 100644
--- a/src/tparse/tree-list.go
+++ b/src/tparse/tree-list.go
@@ -32,7 +32,7 @@ func getClosing(start string) string {
// Parse a list of values
func parseValueList(tokens *[]Token, tok, max int) (Node, int) {
out := Node{}
- out.Data = Token{Type: 10, Data: "list"}
+ out.Data = Token{Type: 10, Data: "value"}
var tmp Node
c := getClosing((*tokens)[tok].Data)
@@ -58,48 +58,9 @@ func parseValueList(tokens *[]Token, tok, max int) (Node, int) {
return out, tok
}
-// Parses a list of definitions
-func parseDefList(tokens *[]Token, tok, max int) (Node, int) {
- out := Node{}
- out.Data = Token{Type: 9, Data: "list"}
-
- currentType := Node{}
- currentType.Data = Token{Data: "undefined"}
-
- c := getClosing((*tokens)[tok].Data)
-
- tok++
-
- for ; tok < max; tok++ {
- switch (*tokens)[tok].Data {
- case c:
- return out, tok
- case ",":
- tok++
- default:
- errOut("Unexpected token when reading parameter definition", (*tokens)[tok])
- }
-
- t := (*tokens)[tok+1]
-
- if t.Data != "," && t.Data != c {
- currentType, tok = parseType(tokens, tok, max, true)
- }
-
- t = (*tokens)[tok]
-
- if t.Type != DEFWORD {
- errOut("Unexpected token in parameter definition. Expected variable identifier", t)
- }
-
- }
-
- return out, tok
-}
-
func parseTypeList(tokens *[]Token, tok, max int) (Node, int) {
out := Node{}
- out.Data = Token{Type: 9, Data: "list"}
+ out.Data = Token{Type: 10, Data: "type"}
var tmp Node
c := getClosing((*tokens)[tok].Data)
@@ -127,7 +88,7 @@ func parseTypeList(tokens *[]Token, tok, max int) (Node, int) {
func parseStatementList(tokens *[]Token, tok, max int) (Node, int) {
out := Node{}
- out.Data = Token{Type: 9, Data: "list"}
+ out.Data = Token{Type: 10, Data: "statement"}
var tmp Node
c := getClosing((*tokens)[tok].Data)
diff --git a/src/tparse/tree-statement.go b/src/tparse/tree-statement.go
index f6d3452..938e827 100644
--- a/src/tparse/tree-statement.go
+++ b/src/tparse/tree-statement.go
@@ -18,24 +18,55 @@ package tparse
func parseBlock(tokens *[]Token, tok, max int) (Node, int) {
out := Node{}
- out.Data = Token{Type: 9, Data: "list"}
+ out.Data = Token{Type: 10, Data: "block"}
var tmp Node
tok++
- for ; tok < max; tok++ {
+ for ;tok < max; tok++{
+ t := (*tokens)[tok]
+
+ switch t.Type {
+ case DELIMIT:
+ if t.Data == "(" {
+
+ } else if t.Data == "(" {
+
+ } else {
+ goto BREAK
+ }
+ case DEFWORD:
+ case KEYWORD:
+ case LINESEP:
+ goto BREAK
+ }
+ }
+
+ BREAK:
+
+ for ;tok < max; {
t := (*tokens)[tok]
switch t.Data {
- case ")", "]", "}":
+ case ";/", ";;", ";:":
return out, tok
- case ",":
- tok++
+ case ";":
+ tmp, tok = parseStatement(tokens, tok, max)
+ case "/;":
+ REBLOCK:
+
+ tmp, tok = parseBlock(tokens, tok, max)
+
+ if (*tokens)[tok].Data == ";;" {
+ out.Sub = append(out.Sub, tmp)
+ goto REBLOCK
+ } else if (*tokens)[tok].Data == ";/" {
+ tok++
+ }
default:
- errOut("Error: unexpected token when parsing a list of types", t)
+ errOut("Error: unexpected token when parsing a code block", t)
}
- tmp, tok = parseType(tokens, tok, max, true)
out.Sub = append(out.Sub, tmp)
}
@@ -44,7 +75,7 @@ func parseBlock(tokens *[]Token, tok, max int) (Node, int) {
func parseStatement(tokens *[]Token, tok, max int) (Node, int) {
out := Node{}
- out.Data = Token{Type: 9, Data: "list"}
+ out.Data = Token{Type: 11, Data: ";"}
var tmp Node
tok++
@@ -52,10 +83,10 @@ func parseStatement(tokens *[]Token, tok, max int) (Node, int) {
for ; tok < max; tok++ {
t := (*tokens)[tok]
- switch t.Data {
- case ")", "]", "}":
+ switch t.Type {
+ case LINESEP, DELIMIT:
return out, tok
- case ",":
+ case INLNSEP:
tok++
default:
errOut("Error: unexpected token when parsing a list of types", t)
@@ -70,7 +101,7 @@ func parseStatement(tokens *[]Token, tok, max int) (Node, int) {
func parseDef(tokens *[]Token, tok, max int) (Node, int) {
out := Node{}
- out.Data = Token{Type: 9, Data: "list"}
+ out.Data = Token{Type: 10, Data: "list"}
var tmp Node
tok++
diff --git a/src/tparse/tree-value.go b/src/tparse/tree-value.go
index 1a057d4..d03383e 100644
--- a/src/tparse/tree-value.go
+++ b/src/tparse/tree-value.go
@@ -16,6 +16,74 @@
package tparse
+// Ops order in TNSL
+// Cast/Paren > Address > Get > Inc/Dec > Math > Bitwise > Logic
+
+var ORDER = map[string]int{
+ // Address of
+ "~": 0,
+ // De-ref
+ "`": 0,
+
+ // Get
+ ".": 1,
+
+ // Inc/Dec
+ "++": 2,
+ "--": 2,
+
+ // Multiplication
+ "*": 3,
+ // Division
+ "/": 3,
+
+ // Addition
+ "+": 4,
+ // Subtraction
+ "-": 4,
+
+ // Mod
+ "%": 5,
+
+ // Bitwise and
+ "&": 6,
+ // Bitwise or
+ "|": 6,
+ // Bitwise xor
+ "^": 6,
+
+ // Bitwise l-shift
+ "<<": 6,
+ // Bitwise r-shift
+ ">>": 6,
+
+ "!&": 6,
+ "!|": 6,
+ "!^": 6,
+
+ // Not (prefix any bool or bitwise)
+ "!": 6,
+
+ // Boolean and
+ "&&": 7,
+ // Boolean or
+ "||": 7,
+ // Truthy equals
+ "==": 7,
+
+ // Greater than
+ ">": 7,
+ // Less than
+ "<": 7,
+
+ "!&&": 7,
+ "!||": 7,
+ "!==": 7,
+
+ "!>": 7,
+ "!<": 7,
+}
+
func parseValue(tokens *[]Token, tok, max int) (Node, int) {
out := Node{}
@@ -33,9 +101,48 @@ func parseValue(tokens *[]Token, tok, max int) (Node, int) {
func parseVoidType(tokens *[]Token, tok, max int) (Node, int) {
out := Node{}
+ working := &out
for ; tok < max; tok++ {
- //t := (*tokens)[tok]
+ t := (*tokens)[tok]
+ switch t.Type {
+ case AUGMENT:
+ if t.Data != "~" && t.Data != "`" {
+ errOut("Error: unexpected augment token when parsing type", t)
+ }
+ working.Data = t
+
+ case KEYTYPE:
+ if t.Data == "void" {
+ *working, tok = parseVoidType(tokens, tok, max)
+ } else {
+ working.Data = t
+ }
+
+ return out, tok
+
+ case DEFWORD:
+
+ case DELIMIT:
+ if t.Data == "{" && tok < max-1 {
+ if (*tokens)[tok+1].Data == "}" {
+ working.Data = Token{AUGMENT, "{}", t.Line, t.Char}
+ tok++
+ } else {
+ errOut("Error: start of list when parsing type (did you mean \"{}\"?)", t)
+ }
+ } else if tok >= max-1 {
+ errOut("Error: unexpected end of file when parsing type", t)
+ } else {
+ errOut("Error: unexpected delimeter when parsing type", t)
+ }
+
+ default:
+ errOut("Error: unexpected token when parsing type", t)
+ }
+
+ makeParent(working, Node{})
+ working = &(working.Sub[0])
}
return out, tok
@@ -49,7 +156,7 @@ func parseType(tokens *[]Token, tok, max int, param bool) (Node, int) {
t := (*tokens)[tok]
switch t.Type {
case AUGMENT:
- if t.Data != "~" {
+ if t.Data != "~" && t.Data != "`" {
errOut("Error: unexpected augment token when parsing type", t)
}
working.Data = t
@@ -70,22 +177,33 @@ func parseType(tokens *[]Token, tok, max int, param bool) (Node, int) {
case KEYWORD:
if param && t.Data == "static" {
+ // Nonstandard keyword in parameter definition
errOut("Error: parameter types cannot be static", t)
} else if t.Data != "const" && t.Data != "volatile" && t.Data != "static" {
+ // Nonstandard keyword in variable definition
errOut("Error: unexpected keyword when parsing type", t)
}
working.Data = t
case DELIMIT:
- if t.Data == "{" {
+ if t.Data == "{" && tok < max-1 {
+ // What happens when an array type is defined
if (*tokens)[tok+1].Data == "}" {
- working.Data = Token{9, "array", t.Line, t.Char}
+ // Length variable array
+ working.Data = Token{AUGMENT, "{}", t.Line, t.Char}
tok++
+ } else if (*tokens)[tok+1].Type == LITERAL {
+ // Array with constant length
} else {
- errOut("Error: start of list when parsing type (did you mean {} ?)", t)
+ // Undefined behaviour
+ errOut("Error: start of list when parsing type (did you mean \"{}\"?)", t)
}
+ } else if tok >= max-1 {
+ // End of file with open delimiter after type parsing has begun
+ errOut("Error: unexpected end of file when parsing type", t)
} else {
- errOut("Error: start of list when parsing type", t)
+ // Other delimiter than {} used in variable definition
+ errOut("Error: unexpected delimeter when parsing type", t)
}
default:
diff --git a/src/tparse/tree.go b/src/tparse/tree.go
index 0b7baf4..9e9e554 100644
--- a/src/tparse/tree.go
+++ b/src/tparse/tree.go
@@ -18,7 +18,8 @@ package tparse
import "fmt"
-// ID 9 = ast thing
+// ID 9 = ast root
+// ID 10 = ast list
func errOut(message string, token Token) {
fmt.Println(message)
@@ -32,7 +33,6 @@ func MakeTree(tokens *[]Token, file string) Node {
out.Data = Token{9, file, 0, 0}
tmp := Node{}
- working := &tmp
max := len(*tokens)
@@ -40,19 +40,18 @@ func MakeTree(tokens *[]Token, file string) Node {
t := (*tokens)[tok]
switch t.Data {
case "/;":
-
+ tmp, tok = parseBlock(tokens, tok, max)
case ";":
-
+ tmp, tok = parseStatement(tokens, tok, max)
case "/:":
-
+ tmp = Node{}
case ":":
-
+ tmp = Node{}
default:
errOut("Unexpected token in file root", t)
}
- tmp = Node{Data: t}
- working.Sub = append(working.Sub, tmp)
+ out.Sub = append(out.Sub, tmp)
}
return out
diff --git a/src/tparse/type.go b/src/tparse/type.go
index 70d8776..73bb94d 100644
--- a/src/tparse/type.go
+++ b/src/tparse/type.go
@@ -50,8 +50,11 @@ var PREWORDS = []string{
"extern",
"size",
"align",
+ "origin",
+ "rootfile",
"if",
"else",
+ "abi",
//"mark",
}
@@ -128,7 +131,7 @@ var RESWORD = map[string]int{
"module": KEYWORD,
"export": KEYWORD,
- "_": KEYWORD,
+ "drop": KEYWORD,
}
func checkResWord(s string) int {
diff --git a/tests/block-test.tnsl b/tests/block-test.tnsl
index 9f25526..6dde05f 100644
--- a/tests/block-test.tnsl
+++ b/tests/block-test.tnsl
@@ -46,15 +46,22 @@
/; module vec
- ;struct Vector2 {x, y int}
+ ;struct Vector2 {int32 x, y}
- /;method ~Vector2
+ /;method Vector2
- /; operator + (v ~Vector2)
+ /; operator + (~Vector2 v)
;self.x += `v.x
;self.y += `v.y
;/
+ /; operator + (int32 a)
+ ;self.x += a
+ ;self.y += a
+ ;/
+
;/
+ ;struct FVector2 () {}
+
;/ \ No newline at end of file
diff --git a/tests/parameter-test.tnsl b/tests/parameter-test.tnsl
index 2c39cb9..254db75 100644
--- a/tests/parameter-test.tnsl
+++ b/tests/parameter-test.tnsl
@@ -14,5 +14,5 @@
limitations under the License.
#/
-/; loop (int initial = 0, int complex = 2) [initial < max || complex < 40, initial++, complex += 7, another += 2]
+/; loop (int initial = 0, complex = 2) [initial < max || complex < 40, initial++, complex += 7, another += 2]
;/
diff --git a/tests/run-tests.sh b/tests/run-tests.sh
index 2443823..6cebbe7 100755
--- a/tests/run-tests.sh
+++ b/tests/run-tests.sh
@@ -2,17 +2,11 @@ PARSECMD=../build/parse
PARSEFILE=" "
parse () {
- $PARSECMD -in $PARSEFILE-test.tnsl -out $PARSEFILE-test.tnt
+ $PARSECMD -in $1-test.tnsl -out $1-test.tnt
}
-PARSEFILE=block
-parse
-
-PARSEFILE=comment
-parse
-
-PARSEFILE=literal
-parse
-
-PARSEFILE=parameter
-parse \ No newline at end of file
+parse block
+parse comment
+parse literal
+parse parameter
+parse statement \ No newline at end of file
diff --git a/tests/statement-test.tnsl b/tests/statement-test.tnsl
new file mode 100644
index 0000000..71bd64b
--- /dev/null
+++ b/tests/statement-test.tnsl
@@ -0,0 +1,6 @@
+/; small_block
+;/
+
+/; if_block
+;; else_block
+;/ \ No newline at end of file