diff options
| author | Kyle Gunger <kgunger12@gmail.com> | 2021-04-30 14:06:58 -0400 | 
|---|---|---|
| committer | Kyle Gunger <kgunger12@gmail.com> | 2021-04-30 14:06:58 -0400 | 
| commit | c625ed1cfe7f7ea4ab2a75a8a0a6a6772f86431c (patch) | |
| tree | 55aab8a27a6cd3b0a979002afa6899a4bda94b74 | |
| parent | 60f7c4f7272079e635010e464d8ce3a3a427f97f (diff) | |
Destroy my own code by using goto
| -rwxr-xr-x | gobuild.sh | 1 | ||||
| -rw-r--r-- | out.tnp | 1 | ||||
| -rw-r--r-- | qualifiers.txt | 71 | ||||
| -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.tnt | 1 | ||||
| -rw-r--r-- | small-tests/test.tnsl | 13 | ||||
| -rw-r--r-- | spec/compiler/compiler.txt | 9 | ||||
| -rw-r--r-- | spec/compiler/pre-processor.txt | 6 | ||||
| -rw-r--r-- | spec/iex/iex-spec.txt | 128 | ||||
| -rw-r--r-- | spec/libts.txt | 93 | ||||
| -rw-r--r-- | spec/spec.txt | 97 | ||||
| -rw-r--r-- | src/main.go | 2 | ||||
| -rw-r--r-- | src/tparse/resolver.go | 24 | ||||
| -rw-r--r-- | src/tparse/tree-list.go | 45 | ||||
| -rw-r--r-- | src/tparse/tree-statement.go | 55 | ||||
| -rw-r--r-- | src/tparse/tree-value.go | 130 | ||||
| -rw-r--r-- | src/tparse/tree.go | 15 | ||||
| -rw-r--r-- | src/tparse/type.go | 5 | ||||
| -rw-r--r-- | tests/block-test.tnsl | 13 | ||||
| -rw-r--r-- | tests/parameter-test.tnsl | 2 | ||||
| -rwxr-xr-x | tests/run-tests.sh | 18 | ||||
| -rw-r--r-- | tests/statement-test.tnsl | 6 | 
23 files changed, 602 insertions, 133 deletions
| @@ -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 |