├── README.md ├── compiler ├── gear ├── gear_language_v04.pdf ├── gearlib │ ├── arrays.gear │ ├── math.gear │ ├── ranges.gear │ ├── readme.md │ ├── sets.gear │ ├── strings.gear │ └── typeinfo.gear ├── readme.md ├── source │ ├── gear.lpi │ ├── gear.lpr │ ├── gear.lps │ ├── readme.md │ ├── uDefines.inc │ ├── uast.pas │ ├── ubaseparser.pas │ ├── uchunk.pas │ ├── ucodegen.pas │ ├── ucommon.pas │ ├── udebug.pas │ ├── uerror.pas │ ├── uexprparser.pas │ ├── ulexer.pas │ ├── umain.pas │ ├── umemory.pas │ ├── unative.pas │ ├── uobject.pas │ ├── uparselets.pas │ ├── uparser.pas │ ├── uprecedence.pas │ ├── uprinter.pas │ ├── ureader.pas │ ├── uresolver.pas │ ├── uscopes.pas │ ├── utable.pas │ ├── utoken.pas │ ├── uvalue.pas │ ├── uvisitor.pas │ └── uvm.pas └── test │ ├── arr0ay.gear │ ├── array0.gear │ ├── array1.gear │ ├── array2.gear │ ├── array4.gear │ ├── array5.gear │ ├── array6.gear │ ├── array7.gear │ ├── array8.gear │ ├── array_num.gear │ ├── arrays7.gear │ ├── arrays8.gear │ ├── arrayslice.gear │ ├── arraytest.gear │ ├── char3a.gear │ ├── char3b.gear │ ├── char3c.gear │ ├── char4.gear │ ├── char5.gear │ ├── class1.gear │ ├── class2.gear │ ├── classname.gear │ ├── colors.gear │ ├── complex.gear │ ├── dec2hex.gear │ ├── deci.gear │ ├── default.gear │ ├── default1.gear │ ├── defer.gear │ ├── defer2.gear │ ├── defer4.gear │ ├── defer5.gear │ ├── dict.gear │ ├── dict05.gear │ ├── dict1.gear │ ├── dict3.gear │ ├── dict5.gear │ ├── dictio.gear │ ├── dictionary.gear │ ├── ensure.gear │ ├── enum.gear │ ├── enum1.gear │ ├── enum2.gear │ ├── factorial.gear │ ├── fibonacci.gear │ ├── filetest.gear │ ├── filetest2.gear │ ├── filetest3.gear │ ├── for2.gear │ ├── format.gear │ ├── func1.gear │ ├── func2.gear │ ├── func3.gear │ ├── gettersetter.gear │ ├── guess.gear │ ├── hanoi.gear │ ├── hex.gear │ ├── hex2.gear │ ├── if.gear │ ├── in.gear │ ├── indexed.gear │ ├── indexer.gear │ ├── inherit.gear │ ├── inherit1.gear │ ├── inherit3.gear │ ├── instance1.gear │ ├── instance3.gear │ ├── lambda.gear │ ├── lambda2.gear │ ├── list.gear │ ├── list1.gear │ ├── list2.gear │ ├── listb.gear │ ├── listcomp.gear │ ├── listcomp1.gear │ ├── listcomp2.gear │ ├── listcomp4.gear │ ├── loop2.gear │ ├── loop3.gear │ ├── loopnew.gear │ ├── mandelbrot1.gear │ ├── map_alt.gear │ ├── match.gear │ ├── match1.gear │ ├── match3.gear │ ├── match4.gear │ ├── matrix.gear │ ├── money.gear │ ├── nilcheck.gear │ ├── nilcheck1.gear │ ├── number.gear │ ├── overload.gear │ ├── overload1.gear │ ├── people.gear │ ├── person.gear │ ├── point.gear │ ├── point1.gear │ ├── primes0.gear │ ├── primes01.gear │ ├── primes3.gear │ ├── private.gear │ ├── private2.gear │ ├── question.gear │ ├── range.gear │ ├── readme.md │ ├── repeat.gear │ ├── satisfy.gear │ ├── scores.gear │ ├── sequence.gear │ ├── set.gear │ ├── set1.gear │ ├── set2.gear │ ├── setbuilder.gear │ ├── smileys.gear │ └── smileys1.gear └── interpreter ├── README.md ├── doc ├── GearLang - An interpreter in Free Pascal - external visitor pattern.pdf ├── The Gear language description.pdf └── readme.md ├── examples ├── .gitkeep ├── add.gear ├── animals.gear ├── anon.gear ├── anonym.gear ├── area.gear ├── array.gear ├── ascii.gear ├── booltest.gear ├── chars.gear ├── class.gear ├── class1.gear ├── class2.gear ├── class3.gear ├── classclass.gear ├── count.gear ├── curry.gear ├── dict.gear ├── dict2.gear ├── dictio.gear ├── double.gear ├── elif.gear ├── elseif.gear ├── elseif2.gear ├── enum.gear ├── expr.gear ├── fib.gear ├── fibonacci.gear ├── file.gear ├── files.gear ├── files2.gear ├── find.gear ├── fizzbuzz.gear ├── for-each-if.gear ├── foreach.gear ├── func.gear ├── funcasparam.gear ├── funcclass.gear ├── hanoi.gear ├── hello.gear ├── helloWorld.gear ├── ifthen.gear ├── ifvar.gear ├── initclosure.gear ├── integral.gear ├── interpol.gear ├── interpol2.gear ├── is.gear ├── iter.gear ├── linsearch.gear ├── listbuild.gear ├── mandelbrot.gear ├── match.gear ├── matrix.gear ├── missing.gear ├── multiline.gear ├── mutability.gear ├── nested.gear ├── num2str.gear ├── overload.gear ├── people.gear ├── person.gear ├── point.gear ├── primes.gear ├── primes2.gear ├── primes3.gear ├── primes4.gear ├── puzzle.gear ├── puzzle15.gear ├── puzzle2.gear ├── random.gear ├── range.gear ├── range1.gear ├── range2.gear ├── range3.gear ├── range4.gear ├── range5.gear ├── roots.gear ├── simple.gear ├── smileys.gear ├── speed.gear ├── stack.gear ├── standard.gear ├── steps.gear ├── str.gear ├── str1.gear ├── str2.gear ├── str3.gear ├── string.gear ├── switch.gear ├── switchregr.gear ├── test.gear ├── trait.gear ├── tuple.gear ├── tuples.gear ├── twice.gear ├── vardecl.gear └── words.gear ├── gear.lpi ├── gear.lpr ├── gear.lps ├── gearlib ├── arrays.gear ├── collections.gear ├── dictionaries.gear ├── ranges.gear ├── strings.gear └── system.gear ├── helloWorld.gear ├── lexer-parser ├── ast.gear ├── errors.gear ├── lexer.gear ├── main.gear ├── parser.gear ├── printer.gear ├── reader.gear ├── readme.md ├── token.gear ├── tokentype.gear └── visitor.gear ├── readme ├── uArray.pas ├── uArrayIntf.pas ├── uCallable.pas ├── uClass.pas ├── uClassIntf.pas ├── uDict.pas ├── uDictIntf.pas ├── uEnum.pas ├── uEnumIntf.pas ├── uFunc.pas ├── uMembers.pas ├── uMemory.pas ├── uResolver.pas ├── uVariantSupport.pas ├── uarray.pas ├── uarrayintf.pas ├── uast.pas ├── ucallable.pas ├── uclass.pas ├── uclassintf.pas ├── ucollections.pas ├── udict.pas ├── udictintf.pas ├── uenum.pas ├── uenumintf.pas ├── uerror.pas ├── ufunc.pas ├── uhash.pas ├── uinterpreter.pas ├── ulanguage.pas ├── ulexer.pas ├── umath.pas ├── umembers.pas ├── umemory.pas ├── uparser.pas ├── uprinter.pas ├── ureader.pas ├── uresolver.pas ├── ustandard.pas ├── ustandardcrt.pas ├── ustandardfiles.pas ├── ustandardlist.pas ├── utils_.pas ├── utoken.pas ├── utuple.pas ├── utupleintf.pas └── uvisitor.pas /README.md: -------------------------------------------------------------------------------- 1 | # Gear Language 2 | A programming language interpreter and compiler written in Free Pascal and Lazarus 3 | 4 | The latest project can be found in folder 'compiler'. 5 | Both 'interpreter' and 'compiler' contain documentation about the Gear language implementation. There are differences, since the language has evolved a bit over the last 2 years. 6 | Both projects were developed using Lazarus with Free Pascal. The latest version of them can be found at: 7 | 8 | https://www.lazarus-ide.org/index.php 9 | 10 | Both the Lazarus ide and the Free Pascal compiler are free. 11 | -------------------------------------------------------------------------------- /compiler/gear: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdehaan2014/GearLanguage/04a861a8020a1a6a2c26e86896dac943d4655805/compiler/gear -------------------------------------------------------------------------------- /compiler/gear_language_v04.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdehaan2014/GearLanguage/04a861a8020a1a6a2c26e86896dac943d4655805/compiler/gear_language_v04.pdf -------------------------------------------------------------------------------- /compiler/gearlib/arrays.gear: -------------------------------------------------------------------------------- 1 | 2 | extension Array is 3 | 4 | val isEmpty := self.count = 0 5 | 6 | func each(function) do 7 | for var element in self do 8 | function(element) 9 | end 10 | end 11 | 12 | func reduce(initialValue, nextValue) do 13 | var result := initialValue 14 | for var element in self do 15 | result := nextValue(result, element) 16 | end 17 | return result 18 | end 19 | 20 | func filter(include) do 21 | var result := [] 22 | for var element in self where include(element) do 23 | result.add(element) 24 | end 25 | return result 26 | end 27 | 28 | func map(transform) do 29 | var result := [] 30 | for var element in self do 31 | result.add(transform(element)) 32 | end 33 | return result 34 | end 35 | 36 | func flatMap(transform) do 37 | return self.map(transform).reduce([],/\(x,y)=>x+y) 38 | end 39 | 40 | func reversed() do 41 | var result := [] 42 | let count := self.count 43 | for var i in 0..(other) => not (self = other) 64 | 65 | end 66 | 67 | -------------------------------------------------------------------------------- /compiler/gearlib/math.gear: -------------------------------------------------------------------------------- 1 | use ranges 2 | 3 | /* module math 4 | math functions and constants 5 | */ 6 | 7 | let Pi := pi() 8 | let E := exp(1) 9 | 10 | //print(Pi) 11 | //print(E) 12 | 13 | // calculate the integral over a function over a range in n steps 14 | 15 | func integral(f, from a, to b, steps n) do 16 | var sum := 0 17 | let dt := (b-a)/n 18 | for var i := 0 where ix^2-2*x+4, from: 0, to: 1, steps: 10000)) 26 | 27 | // Calculate the integral over function f(x) = x^3 in 10000 steps 28 | //print(integral(/\x=>x^3, from: 0, to: 1, steps: 10000)) 29 | 30 | // Calculate the integral over function 3) f(x) = x^2 + 4*x - 21 in 10000 steps 31 | //print(integral(x=>x^2 + 4*x - 21, from: 0, to: 1, steps: 10000)) 32 | 33 | // integral of half circle 34 | // x^2 + y^2 = 1 35 | // y^2 = 1 - x^2 36 | // y = sqrt(1-x^2) 37 | //print(integral(/\x=>sqrt(1-x^2), from: -1, to: 1, steps: 10000)) // pi/2 38 | 39 | //Calculate Pi 40 | //let Pi := 2 * integral(/\x=>sqrt(1-x^2), from: -1, to: 1, steps: 100000) 41 | 42 | //print(Pi) 43 | //print(pi()) // compare 44 | 45 | 46 | // return a random integer number between an interval (a,b) 47 | 48 | func random(between a, b) do 49 | randomize() 50 | return random(b-a)+a 51 | end 52 | 53 | /* 54 | print(random(between: 5, 10)) 55 | print(random(between: 10, 20)) 56 | print(random(between: 50, 100)) 57 | */ 58 | 59 | 60 | func random(.interval) do 61 | randomize() 62 | return random(interval.to - interval.from) + interval.from 63 | end 64 | 65 | //print(random(interval: 0..100)) 66 | 67 | func hypotenusa(x,y) do 68 | ensure y <> 0 else 69 | return 0 70 | end 71 | if let r := y/x where x>y then 72 | return x*sqrt(1+r*r) 73 | end 74 | return y*sqrt(1+(x/y)^2) 75 | end 76 | 77 | // var y := hypotenusa(4,3) 78 | 79 | // convert decimal number to hexadecimal string 80 | func dec2hex(n) do 81 | var hex := '' 82 | while n<>0 do 83 | var temp := 0 84 | temp := n%16 85 | 86 | if temp<10 then 87 | hex += chr(temp+48) 88 | else 89 | hex += chr(temp+55) 90 | end 91 | 92 | n := trunc(n/16) 93 | end 94 | 95 | var result := '' 96 | for var i:= length(hex)-1 where i>=0, i-=1 do 97 | result += hex[i] 98 | end 99 | 100 | result := length(result) = 0 ? 101 | true: '00' 102 | false: length(result) = 1? 103 | true: '0' + result 104 | false: result 105 | 106 | return result 107 | end 108 | 109 | // recursive solution 110 | func toHex(d) do 111 | let chars := '0123456789ABCDEF' 112 | var r := d % 16 113 | if d - r = 0 then 114 | return chars[r] 115 | end 116 | return toHex((d - r) / 16) + chars[r] 117 | end 118 | 119 | // var h := Dec2Hex(28452345) // 1B225F9 120 | 121 | func toBin(n) do 122 | var bin := '' 123 | do 124 | bin := n % 2 = 0 ? 125 | true: '0' + bin 126 | false: '1' + bin 127 | n := trunc(n / 2) 128 | end while n<>0 129 | return bin 130 | end 131 | 132 | // faster solution using bitwise 'and' + shift right 133 | func dec2bin(n) do 134 | var bin := '' 135 | while n > 0 do 136 | bin := n & 1 = 1 ? 137 | true: '1' + bin 138 | false: '0' + bin 139 | n := n >> 1 140 | end 141 | return bin 142 | end 143 | 144 | //print(dec2Bin(256)) 145 | //print(0b100000000) 146 | //print(toBin(7)) 147 | //print(toBin(256)) 148 | 149 | -------------------------------------------------------------------------------- /compiler/gearlib/ranges.gear: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Defines Range extensions. 4 | */ 5 | 6 | extension Range is 7 | 8 | func each(function) do 9 | for var item in self do 10 | function(item) 11 | end 12 | end 13 | 14 | func reduce(initialValue, nextValue) do 15 | var result := initialValue 16 | for var item in self do 17 | result := nextValue(result, item) 18 | end 19 | return result 20 | end 21 | 22 | func filter(includeElement) do 23 | var result := [] 24 | for var item in self where includeElement(item) do 25 | result.add(item) 26 | end 27 | return result 28 | end 29 | 30 | func map(transform) do 31 | var result := [] 32 | for var item in self do 33 | result.add(transform(item)) 34 | end 35 | return result 36 | end 37 | 38 | func contains(.value) do 39 | return value in self 40 | end 41 | 42 | end 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /compiler/gearlib/readme.md: -------------------------------------------------------------------------------- 1 | this contains the library files of Gear 2 | -------------------------------------------------------------------------------- /compiler/gearlib/sets.gear: -------------------------------------------------------------------------------- 1 | // set extensions 2 | 3 | extension Set is 4 | 5 | val isEmpty := self.count = 0 6 | 7 | func each(function) do 8 | for var element in self do 9 | function(element) 10 | end 11 | end 12 | 13 | func reduce(initialValue, nextValue) do 14 | var result := initialValue 15 | for var element in self do 16 | result := nextValue(result, element) 17 | end 18 | return result 19 | end 20 | 21 | func filter(includeElement) do 22 | var result := {} 23 | 24 | for var item in self where includeElement(item) do 25 | result.add(item) 26 | end 27 | 28 | return result 29 | end 30 | 31 | func map(transform) do 32 | var result := {} 33 | 34 | for var item in self do 35 | result.add(transform(item)) 36 | end 37 | 38 | return result 39 | end 40 | 41 | func flatMap(transform) do 42 | return self.map(transform).reduce([],/\(x,y)=>x+y) 43 | end 44 | 45 | end 46 | 47 | -------------------------------------------------------------------------------- /compiler/gearlib/strings.gear: -------------------------------------------------------------------------------- 1 | //module strings.gear 2 | // standard string routines 3 | 4 | // copies part of a string from start for count characters 5 | func copy(.string, .start, .count) do 6 | var result := '' 7 | var len := length(string) 8 | if len > start+count then 9 | len := start+count 10 | end 11 | for var i := start where i Type.Number then 41 | print('wrong') 42 | end 43 | 44 | let value := false 45 | if type(of: value) = Type.Boolean then 46 | print('Yes indeed') 47 | end 48 | 49 | let str := 'Hello' 50 | if type(of: str) = Type.String then 51 | print('It sure is') 52 | end 53 | */ 54 | 55 | //print(type(of: x=>x^2)) // Func 56 | 57 | -------------------------------------------------------------------------------- /compiler/readme.md: -------------------------------------------------------------------------------- 1 | # Gear scripting language 2 | 3 | Gear is a so-called multi-paradigm programming language. It is imperative, functional, class oriented and partially dynamic. It supports type inference, and in fact doesn’t have a static type system, but still is type-safe. Gear is case sensitive! 4 | As a sort of tradition, every language’s first program prints ‘Hello world!’. In Gear, this program can be written in a single line: 5 | 6 | print('Hello world!') 7 | 8 | This is a full program; there’s no need for a main() function or some other entry point. A program can be a simple statement. 9 | If you want to make it more interesting you can also use: 10 | 11 | a regular function: 12 | 13 | ``` 14 | func helloworld() do 15 | print('Hello world!') 16 | end 17 | helloWorld() 18 | ``` 19 | a lambda expression: 20 | 21 | ``` 22 | var helloWorld := lambda() do 23 | print('Hello world!') 24 | end 25 | helloWorld() 26 | ``` 27 | a function with named parameter and string interpolation: 28 | 29 | ``` 30 | func greetings(to name) do 31 | print('Hello $(name)!') 32 | end 33 | greetings(to: 'world') 34 | ``` 35 | Gear doesn’t look like C-type programs, meaning there are no curly braces to create blocks of code. It aims for readability. 36 | Semicolons are not used to separate statements from each other. 37 | An assignment is done via the ‘:=’ token, and testing for equality just requires a single ‘=’ token. 38 | Gear supports functions, records, classes, higher order functions, arrays, dictionaries, sets and much more. 39 | Gear runs on GearVM, which (currently) is built into the compiler, so compile and run at the same time! 40 | 41 | run a Gear program as follows: 42 | > gear -c -f filename.gear 43 | 44 | Use the accomanied MacOs binary 'gear' or compile for any other platform with Lazarus & Free Pascal. Also, add the complete gearlib/ folder as a separate folder into the same folder as the gear binary. 45 | 46 | -------------------------------------------------------------------------------- /compiler/source/readme.md: -------------------------------------------------------------------------------- 1 | This is a Lazarus/FreePascal project 2 | -------------------------------------------------------------------------------- /compiler/source/uDefines.inc: -------------------------------------------------------------------------------- 1 | // this file contains general defines 2 | 3 | {$DEFINE NAN_BOXING} 4 | 5 | {$DEFINE DEBUG_PRINT_CODE} 6 | //{$DEFINE DEBUG_TRACE_EXECUTION} 7 | //{$DEFINE DEBUG_STRESS_GC} 8 | //{$DEFINE DEBUG_LOG_GC} 9 | 10 | 11 | -------------------------------------------------------------------------------- /compiler/source/ucommon.pas: -------------------------------------------------------------------------------- 1 | unit uCommon; 2 | 3 | {$mode objfpc}{$H+} 4 | {$ModeSwitch typehelpers} 5 | 6 | // Common constants, variables and functions 7 | interface 8 | 9 | uses 10 | SysUtils, fgl; 11 | 12 | const 13 | cByteMax = Byte.MaxValue; // 255 14 | cByteCount = cByteMax + 1; // 256 15 | cMaxCases = 256; // max no of cases in switch statement 16 | cMaxExits = 256; // max no of exits in a loop exit do statement 17 | 18 | cIntSize = SizeOf(Integer); 19 | cByteSize = SizeOf(Byte); 20 | 21 | FileExtension = '.gear'; 22 | 23 | GearVersion = 'version 0.3'; 24 | Year = 2021; 25 | 26 | 27 | type 28 | 29 | TFileNameList = specialize TFPGList; 30 | 31 | 32 | procedure WriteFmt(const Fmt: String; const Args: array of const); 33 | procedure WriteLnFmt(const Fmt: String; const Args: array of const); 34 | procedure WriteFmt(var TextFile: Text; const Fmt: String; const Args: array of const); 35 | procedure WriteLnFmt(var TextFile: Text; const Fmt: String; const Args: array of const); 36 | 37 | // This operator overload allows to check if a class instance has an assigned value 38 | // Instead of doing 39 | // if Assigned(Instance) then .... 40 | // One can now do 41 | // if Instance then ... 42 | //operator := (Obj: TObject): Boolean; 43 | 44 | 45 | var 46 | // folder system 47 | AppFolder, 48 | ProductFolder, 49 | LibraryFolder: TFileName; 50 | FileNameList: TFileNameList; 51 | 52 | implementation 53 | 54 | //operator := (Obj: TObject): Boolean; inline; 55 | //begin 56 | // Result := Assigned(Obj); 57 | //end; 58 | 59 | procedure WriteFmt(const Fmt: String; const Args: array of const); 60 | begin 61 | Write(Format(Fmt, Args)); 62 | end; 63 | 64 | procedure WriteLnFmt(const Fmt: String; const Args: array of const); 65 | begin 66 | WriteLn(Format(Fmt, Args)); 67 | end; 68 | 69 | procedure WriteFmt(var TextFile: Text; const Fmt: String; 70 | const Args: array of const); 71 | begin 72 | Write(TextFile, Format(Fmt, Args)); 73 | end; 74 | 75 | procedure WriteLnFmt(var TextFile: Text; const Fmt: String; 76 | const Args: array of const); 77 | begin 78 | WriteLn(TextFile, Format(Fmt, Args)); 79 | end; 80 | 81 | 82 | initialization 83 | FileNameList := TFileNameList.Create; 84 | finalization 85 | FileNameList.Free; 86 | end. 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /compiler/source/uerror.pas: -------------------------------------------------------------------------------- 1 | unit uError; 2 | 3 | {$mode objfpc}{$H+} 4 | 5 | // Contains the definition of the error class and error list. 6 | 7 | interface 8 | 9 | uses 10 | Classes, SysUtils, uToken, fgl; 11 | 12 | type 13 | 14 | TErrorItem = class 15 | Loc: TLocation; // an error has a location: Line, Col, File 16 | Msg: String; 17 | constructor Create(const Location: TLocation; const Message: String); 18 | function toString: String; override; 19 | end; 20 | 21 | TErrors = class(specialize TFPGObjectList) 22 | private 23 | FHeader: String; 24 | public 25 | constructor Create(const Header: String); 26 | function toString: String; override; 27 | end; 28 | 29 | EParseError = class(Exception); 30 | 31 | procedure AddError(const Location: TLocation; const Message: String); 32 | 33 | var 34 | Errors: TErrors; 35 | 36 | implementation 37 | 38 | { TErrorItem } 39 | 40 | constructor TErrorItem.Create(const Location: TLocation; const Message: String); 41 | begin 42 | Loc := Location; 43 | Msg := Message; 44 | end; 45 | 46 | function TErrorItem.toString: String; 47 | begin 48 | Result := '@' + Loc.toString + ': ' + Msg; 49 | end; 50 | 51 | { TErrors } 52 | 53 | constructor TErrors.Create(const Header: String); 54 | begin 55 | inherited Create(); 56 | FHeader := Header; 57 | end; 58 | 59 | function TErrors.toString: String; 60 | var 61 | Item: TErrorItem; 62 | begin 63 | Result := FHeader + LineEnding; 64 | for Item in Self do 65 | Result += Item.toString + LineEnding; 66 | end; 67 | 68 | 69 | procedure AddError(const Location: TLocation; const Message: String); 70 | begin 71 | Errors.Add(TErrorItem.Create(Location, Message)); 72 | if Errors.Count>30 then 73 | begin 74 | Writeln(Errors.toString); 75 | Halt(65); 76 | end; 77 | end; 78 | 79 | 80 | initialization 81 | Errors := TErrors.Create('[Errors]'); 82 | 83 | finalization 84 | Errors.Free; 85 | end. 86 | 87 | 88 | -------------------------------------------------------------------------------- /compiler/source/uprecedence.pas: -------------------------------------------------------------------------------- 1 | unit uPrecedence; 2 | 3 | {$mode objfpc}{$H+} 4 | 5 | interface 6 | 7 | { 8 | Defines the different precendence levels used by the infix parsers. These 9 | determine how a series of infix expressions will be grouped. For example, 10 | "a + b * c - d" will be parsed as "(a + (b * c)) - d" because "*" has higher 11 | precedence than "+" and "-". Here, bigger numbers mean higher precedence. 12 | 13 | } 14 | 15 | const 16 | precNone = 0; 17 | precPrecision = 1; // <~ 18 | precConditional = 2; // ?: IfExpr 19 | precOr = 3; // or 20 | precAnd = 4; // and 21 | precEquality = 5; // = <> 22 | precComparison = 6; // > >= < <= 23 | precTerm = 7; // + - or xor ~ 24 | precFactor = 8; // * / % and << >> is in 25 | precExponent = 9; // ^ 26 | precRange = 10; // .. ..< 27 | precUnary = 11; // + - not 28 | precCall = 12; // . () [] 29 | precPrimary = 13; // literals 30 | 31 | implementation 32 | 33 | end. 34 | 35 | 36 | -------------------------------------------------------------------------------- /compiler/source/uscopes.pas: -------------------------------------------------------------------------------- 1 | unit uScopes; 2 | 3 | {$mode objfpc}{$H+} 4 | {$ModeSwitch advancedrecords} 5 | 6 | interface 7 | 8 | uses 9 | Classes, SysUtils, fgl; 10 | 11 | type 12 | // Status of a Symbol: Variables need to be Declared or Enabled 13 | // Methods need to be Declared 14 | TStatus = (Declared, Enabled); 15 | 16 | // A symbol can only be used if it is enabled. 17 | // Only variables declared with 'var' are mutable. 18 | // If a variable id declared with 'let' and the initial value is nil, 19 | // then a one time assignment is allowed. 20 | 21 | TMembers = specialize TFPGMap; 22 | 23 | TSymbol = class 24 | Name: String; 25 | Status: TStatus; 26 | Mutable: Boolean; 27 | IsNil: Boolean; 28 | isPrivate: Boolean; // field starting with underscore '_field' 29 | Members: TMembers; 30 | constructor Create(const AName: String; const AStatus: TStatus; 31 | const AMutable: Boolean = False); 32 | destructor Destroy; override; 33 | end; 34 | 35 | // A scope maintains all symbols declared in that scope. Symbols can be 36 | // entered into the scope and they can be looked up again. 37 | // A scope usually has an enclosing scope. Only the global scope doesn't have one. 38 | TScope = class(specialize TFPGMapObject) 39 | private 40 | FEnclosing: TScope; 41 | public 42 | property Enclosing: TScope read FEnclosing; 43 | constructor Create(AEnclosing: TScope=Nil); 44 | procedure Enter(ASymbol: TSymbol); 45 | function Lookup(AName: String): TSymbol; 46 | end; 47 | 48 | // Everytime a new scope is entered, it is pushed on top of the stack. 49 | // The top of stack is the current scope. 50 | TScopes = class(specialize TFPGObjectList) 51 | procedure Push(Item: TScope); 52 | function Pop: TScope; 53 | function Top: TScope; 54 | end; 55 | 56 | implementation 57 | 58 | { TSymbol } 59 | 60 | constructor TSymbol.Create(const AName: String; const AStatus: TStatus; 61 | const AMutable: Boolean); 62 | begin 63 | Name := AName; 64 | Status := AStatus; 65 | Mutable := AMutable; 66 | isNil := False; 67 | isPrivate := AName[1] = '_'; 68 | Members := TMembers.Create; 69 | end; 70 | 71 | destructor TSymbol.Destroy; 72 | begin 73 | Members.Free; 74 | inherited Destroy; 75 | end; 76 | 77 | 78 | { TScope } 79 | 80 | constructor TScope.Create(AEnclosing: TScope); 81 | begin 82 | inherited Create(); 83 | Sorted := True; 84 | FEnclosing := AEnclosing; 85 | end; 86 | 87 | // Enter a symbol to the current scope 88 | procedure TScope.Enter(ASymbol: TSymbol); 89 | begin 90 | Add(ASymbol.Name, ASymbol); 91 | end; 92 | 93 | // First lookup the symbol in the current scope. 94 | // If not found also lookup the enclosing scope(s) recursively. 95 | function TScope.Lookup(AName: String): TSymbol; 96 | var 97 | i: Integer; 98 | begin 99 | if Find(AName, i) then 100 | Result := Data[i] 101 | else if Assigned(FEnclosing) then 102 | Result := FEnclosing.Lookup(AName) 103 | else 104 | Result := Nil; 105 | end; 106 | 107 | { TScopes } 108 | 109 | procedure TScopes.Push(Item: TScope); 110 | begin 111 | Add(Item); // This scope becomes the top of the stack 112 | end; 113 | 114 | function TScopes.Pop: TScope; 115 | begin 116 | Result := Extract(Last); // Throw away the top of the stack 117 | end; 118 | 119 | function TScopes.Top: TScope; 120 | begin 121 | Result := Last; // Last is the lastly added scope and thus the top of the stack 122 | end; 123 | 124 | 125 | end. 126 | 127 | 128 | -------------------------------------------------------------------------------- /compiler/test/arr0ay.gear: -------------------------------------------------------------------------------- 1 | 2 | var a := [1,2,3] 3 | print(length(a)) 4 | 5 | let x := a[1] 6 | print(x) 7 | 8 | let s := 'abcdef' 9 | print(s[2]) 10 | 11 | let d := [1: 'one', 2: 'two', 3:'three'] 12 | print(d[2]) 13 | 14 | a[1] := 4 15 | print(a) 16 | 17 | d[3] := 'three-ish' 18 | print(d) 19 | d[4] := 'four' 20 | print(d) 21 | 22 | s[3] := 'h' 23 | print(s) 24 | 25 | -------------------------------------------------------------------------------- /compiler/test/array0.gear: -------------------------------------------------------------------------------- 1 | 2 | let a := [1,2,3,4,5,6,7,8,9,10] 3 | print(a) 4 | print(a[0]) 5 | 6 | 7 | for var i in [1,2,3,4,5,6,7,8,9,10] where i%2=0 do 8 | print(i, terminator: '|') 9 | end 10 | print() 11 | 12 | for var x in a do 13 | print(x, terminator: '|') 14 | end 15 | print() 16 | 17 | var range := -5..<10 18 | for var i in range do 19 | print(i, terminator: '|') 20 | end 21 | print() 22 | range := (0..30).step(3) 23 | for var i in range do 24 | print(i, terminator: '|') 25 | end 26 | print() 27 | 28 | -------------------------------------------------------------------------------- /compiler/test/array1.gear: -------------------------------------------------------------------------------- 1 | 2 | extension Array is 3 | init(input) do 4 | if input is Array then 5 | return [].add(array: input) 6 | else 7 | return [].add(count: input, value: nil) 8 | end 9 | end 10 | end 11 | 12 | var a := Array([1,2,3,4,5]) 13 | print(a) 14 | 15 | var b := Array(5) 16 | print(b) 17 | 18 | a[1] := 9 19 | print(a) 20 | 21 | a += [1,2,3] 22 | print(a) 23 | 24 | b[1]:=9 25 | b+=[4,5,6] 26 | print(b) 27 | 28 | -------------------------------------------------------------------------------- /compiler/test/array2.gear: -------------------------------------------------------------------------------- 1 | let m := [[1,2],[3,4],[5,6]] 2 | print(m[1][1]) //4 3 | 4 | 5 | let a := [1,2,3,4,5] 6 | for var i:=0 where i < length(a), i:=i+1 do 7 | print(a[i]) 8 | end 9 | 10 | var numbers := [1,2,3,4,5] 11 | numbers := numbers + [6,7,8,9] 12 | print([0] + numbers) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 13 | 14 | //print(numbers + 9) 15 | 16 | extension Array is 17 | 18 | // calculate the sum of all elements using 19 | // recursive tail calls 20 | func summa() => 21 | match @count 22 | if 0: 0 23 | else @head + @tail.summa() 24 | 25 | //multiply 2 arrays 26 | infix *(other) do 27 | var result := [] 28 | for var i in 0..x^2)) 15 | print(list.filter(x=>x%2=0)) 16 | print(list.reduce(0, /\(x,y)=>x+y)) 17 | print(list.sum()) 18 | print(list.reversed()) 19 | 20 | print((3..<10).toArray()) 21 | print((3..<10).toSet()) 22 | var range := 0..<10 23 | print(5 in range) 24 | print(10 in range) 25 | print(9 in range) 26 | print(12 not in range) 27 | 28 | print([ x for x in (0..10).toArray() ]) 29 | print([ x for x in array(of: 'abcdefghik') ]) 30 | for var x in array(of: 'abcdefghik') do 31 | print(x, terminator: '|') 32 | end 33 | print() 34 | 35 | -------------------------------------------------------------------------------- /compiler/test/array5.gear: -------------------------------------------------------------------------------- 1 | 2 | var list := [0,1,2,3,4,5,6,7,8,9] 3 | list.add(10) 4 | print(list[9]) 5 | list[9] := 11 6 | print(list) 7 | 8 | for var item in list where item%2=0 do 9 | print(item, terminator: '|') 10 | end 11 | print() 12 | 13 | //list := [0,1,2,3,4,5,6,7,8,9] 14 | var otherList := [0,1,2,3,4,5,6,7,8,9] 15 | 16 | print(list = otherList) 17 | 18 | print(list <> otherList) 19 | 20 | -------------------------------------------------------------------------------- /compiler/test/array6.gear: -------------------------------------------------------------------------------- 1 | let list := [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] 2 | 3 | print([2*x for x in list where x=>x^2>3]) 4 | print([2*x for x in 0..15 where x=>x^2>3]) 5 | 6 | var evens := list.flatMap(n => if n%2=0 then [n] else []) 7 | print(evens) 8 | 9 | var evensSquared := list.flatMap(n => if n%2=0 then [n*n] else []) 10 | print(evensSquared) 11 | 12 | -------------------------------------------------------------------------------- /compiler/test/array7.gear: -------------------------------------------------------------------------------- 1 | 2 | let a := [].add(count:5, value:0) 3 | 4 | print(a) 5 | 6 | -------------------------------------------------------------------------------- /compiler/test/array8.gear: -------------------------------------------------------------------------------- 1 | var list := [1,2,3,4,5,6,7,8,9,10] 2 | print(list) 3 | 4 | 5 | list.each(/\(n) do 6 | print(n^2, terminator: '|') 7 | end) 8 | print() 9 | 10 | (1..10).each(/\(n) do 11 | print(n^3, terminator: '|') 12 | end) 13 | print() 14 | 15 | print((1..10).reduce(1, /\(x,y)=>x*y)) 16 | print(list[3..9].reduce(0, /\(x,y)=>x+y)) 17 | print(list.reduce(1, /\(x,y)=>x*y)) 18 | 19 | -------------------------------------------------------------------------------- /compiler/test/array_num.gear: -------------------------------------------------------------------------------- 1 | // array with only numbers 2 | 3 | use typeinfo 4 | 5 | extension Array is 6 | func add(number value) do 7 | ensure type(of: value) = Type.Number else 8 | error('Only numbers allowed.') 9 | end 10 | self.add(value) 11 | end 12 | 13 | func all(.satisfy) do 14 | for var item in self where not satisfy(item) do 15 | return false 16 | end 17 | return true 18 | end 19 | end 20 | 21 | var numbers := [] 22 | numbers.add(number: 99) 23 | numbers.add(number: 100) 24 | print(numbers) // [99, 100] 25 | print(numbers.all(satisfy: value=>type(of: value) = Type.Number)) 26 | 27 | //numbers.add(number: 'hello') // Runtime error: Only numbers allowed. 28 | 29 | numbers.add(value: 'hello') 30 | print(numbers) 31 | 32 | print(numbers.all(satisfy: value=>type(of: value) = Type.Number)) 33 | 34 | 35 | -------------------------------------------------------------------------------- /compiler/test/arrays7.gear: -------------------------------------------------------------------------------- 1 | 2 | 3 | let set := {1,2,3,4,5,6,7,8,9} 4 | 5 | let a := [n for n in set] 6 | print(a) 7 | 8 | var result := [ 2*x for x in {1,2,3,4,5,6,7,8,9,10} where x^2>3 ] 9 | print(result) 10 | 11 | //let y := result 12 | 13 | (1..10).each(/\(n) do 14 | print(n) 15 | end) 16 | 17 | -------------------------------------------------------------------------------- /compiler/test/arrays8.gear: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | var a := 1..<9 4 | print(a) 5 | print(a.toArray()) 6 | 7 | let list := (1..<9).toArray() 8 | */ 9 | 10 | var list := [1,2,3,4,5] 11 | print(list) 12 | 13 | list.each(/\(n) do 14 | print(n^2, terminator: '|') 15 | end) 16 | print() 17 | 18 | 19 | print((1..<9).map(x=>x^3)) 20 | 21 | (1..<9).each(/\(n) do 22 | print(n^2, terminator: '|') 23 | end) 24 | print() 25 | 26 | 27 | -------------------------------------------------------------------------------- /compiler/test/arrayslice.gear: -------------------------------------------------------------------------------- 1 | // test array slice 2 | 3 | var a := [1,2,3,4,5,6,7,8,9] 4 | 5 | print(a[2..5]) 6 | print(a[2]) 7 | print(a[5]) 8 | 9 | let b := a[0..<6] 10 | print(b) 11 | 12 | let ar := [1,2,3,4,5,6,7,8,9,10] 13 | print(ar[0..4]) 14 | print(ar[0..<5]) 15 | let s := ar[2..5] 16 | print(ar[4..chr(n))] 3 | print(result) 4 | 5 | for var x in array(of: 34..124) do 6 | print(chr(x), terminator: ' ') 7 | end 8 | 9 | print() 10 | print() 11 | 12 | print((65..90).map(n=>chr(n))) 13 | let alfa := (65..90).map(n=>chr(n)) 14 | 15 | for var c in alfa do 16 | print(c, terminator: '|') 17 | end 18 | 19 | -------------------------------------------------------------------------------- /compiler/test/class1.gear: -------------------------------------------------------------------------------- 1 | class Simple is 2 | var field := 'field' 3 | init(field) for field 4 | func toString() => '(field)' 5 | end 6 | 7 | var simple := Simple('another field') 8 | print(simple.toString(), terminator: '...') 9 | 10 | -------------------------------------------------------------------------------- /compiler/test/class2.gear: -------------------------------------------------------------------------------- 1 | record Date is 2 | var _dd:=1, _mm:=1, _yyyy:=1980 3 | init(dd,mm,yyyy) for _dd,_mm,_yyyy 4 | func toString()=> '$(_dd)-$(_mm)-$(_yyyy)' 5 | end 6 | 7 | class Person is 8 | let _birthDate := Date() 9 | let _name := '' 10 | init(name, birthDate) for _name, _birthDate 11 | func toString() => '$(_name): $(_birthDate.toString())' 12 | end 13 | 14 | var JJ := Person('Jerry', Date(18,01,1998)) 15 | print(JJ.toString()) 16 | 17 | -------------------------------------------------------------------------------- /compiler/test/classname.gear: -------------------------------------------------------------------------------- 1 | // test className variable 2 | // variable className is predefined for each class 3 | 4 | record Vehicle is 5 | var _brand := 'brand' 6 | let type := 'type' 7 | init(brand, type) for _brand, @type 8 | 9 | // getter and setter 10 | val brand := _brand 11 | func set(.brand) do 12 | _brand := brand 13 | end 14 | func set(.type) do 15 | @type := type 16 | end 17 | 18 | func toString() => '$(_brand), $(@type)' 19 | end 20 | 21 | var vehicle := Vehicle('Volvo', 'V90') 22 | print(vehicle.brand) 23 | print(vehicle.type) 24 | print(vehicle.className) 25 | //vehicle.brand := 'Mercedes' // error Cannot assign to value property "brand". 26 | //vehicle.type := 'S class' 27 | //vehicle.test := 5 28 | print(vehicle.toString()) 29 | vehicle.set(brand: 'BMW') 30 | vehicle.set(type: '530i') 31 | print(vehicle.toString()) 32 | 33 | use typeinfo 34 | print(type(of: vehicle)) 35 | print(type(of: Vehicle)) 36 | print(type(of: 5)) 37 | 38 | if type(of: vehicle) = Type.Class then 39 | print(vehicle.className) 40 | end 41 | 42 | var a := [1,2,3] 43 | print(type(of: a)) 44 | 45 | 46 | -------------------------------------------------------------------------------- /compiler/test/colors.gear: -------------------------------------------------------------------------------- 1 | //colors 2 | 3 | use math 4 | 5 | record RGB is 6 | var red := 0, green := 0, blue := 0 7 | init(r,g,b) for self.red, self.green, self.blue 8 | func toString() => '$(self.red)-$(self.green)-$(self.blue)' 9 | func toHexString() => 10 | dec2hex(@red) + dec2hex(@green) + dec2hex(@blue) 11 | end 12 | 13 | enum Color is 14 | Black = RGB(0,0,0), 15 | White = RGB(255,255,255), 16 | Red = RGB(255,0,0), 17 | Green = RGB(0,255,0), 18 | Blue = RGB(0,0,255), 19 | Yellow = RGB(255,255,0), 20 | Orange = RGB(255,128,0), 21 | Purple = RGB(127,0,255) 22 | 23 | func toString() => '$(self.name)' 24 | func valueToString() => @value.toString() 25 | end 26 | 27 | var color := Color.Purple 28 | print(color) 29 | print('color name: $(color.name)') 30 | print('color.value: $(color.value)') 31 | print('color.value2: $(color.value.toString())') 32 | 33 | print('color hex: $(color.value.toHexString())') 34 | 35 | switch color 36 | case .Black: print('Black') 37 | case .White: print('White') 38 | case .Red: print('Red') 39 | case .Green: print('Green') 40 | case .Purple: print('Purple') 41 | default: print('no color') 42 | end 43 | 44 | -------------------------------------------------------------------------------- /compiler/test/complex.gear: -------------------------------------------------------------------------------- 1 | // operator overloading 2 | 3 | record Complex is 4 | var re := 0, im := 0 5 | default _value := '' 6 | init(re, im) do 7 | @re := re 8 | @im := im 9 | _value := @toString() 10 | end 11 | func toString() do 12 | let sign := if @im < 0 then '' else '+' 13 | return '$(@re)$(sign)$(@im)i' 14 | end 15 | end 16 | 17 | extension Complex is 18 | func plus(other) => 19 | Complex(@re + other.re, @im + other.im) 20 | infix +(other) => 21 | Complex(@re + other.re, @im + other.im) 22 | infix >(other) => 23 | sqrt(@re * @im) > sqrt(other.re * other.im) 24 | infix <(other) => 25 | sqrt(@re * @im) < sqrt(other.re * other.im) 26 | infix =(other) => 27 | @re = other.re and @im = other.im 28 | infix <>(other) => not (self = other) 29 | prefix -() => Complex(-@re, -@im) 30 | end 31 | 32 | var c := Complex(3,4) 33 | print(c) 34 | //print(c.toString()) 35 | 36 | var d := Complex(5,3) 37 | print(d) 38 | //print(d.toString()) 39 | print('====') 40 | //let e := c+d 41 | let e := c.plus(d) 42 | print(e) //.toString()) 43 | print(e) 44 | print(e.plus(d)) //.toString()) 45 | 46 | var x := c+d 47 | print('x=',x) 48 | print('x=',x.toString()) 49 | 50 | print(x>d) 51 | print(cd) 56 | 57 | let g := -c+d 58 | print(g) //.toString()) 59 | //print(c<=d) 60 | 61 | 62 | -------------------------------------------------------------------------------- /compiler/test/dec2hex.gear: -------------------------------------------------------------------------------- 1 | //decimal to hex converter 2 | 3 | 4 | func Dec2Hex(n) do 5 | var hex := '' 6 | while n<>0 do 7 | var temp := 0 8 | temp := n%16 9 | 10 | if temp<10 then 11 | hex += chr(temp+48) 12 | else 13 | hex += chr(temp+55) 14 | end 15 | 16 | n := trunc(n/16) 17 | end 18 | 19 | var result := '' 20 | for var i:= length(hex)-1 where i>=0, i-=1 do 21 | result += hex[i] 22 | end 23 | 24 | return result 25 | end 26 | 27 | let x := 28452345 28 | 29 | print('Decimal $(x) = Hex $(Dec2Hex(x)).') // 1B225F9 30 | 31 | -------------------------------------------------------------------------------- /compiler/test/deci.gear: -------------------------------------------------------------------------------- 1 | // test numbers and formatting 2 | 3 | let x := 1.2345 4 | let y := pi() 5 | 6 | print(x+y<~(precision: 15, digits: 5)) // digits ignored 7 | 8 | //print(pi()<~3) // tuple expected 9 | 10 | 11 | let format := (precision: 10, digits: 3) 12 | print(pi()<~format) // returns a string 13 | 14 | format.digits := 2 15 | print((3.12345E3)<~format) 16 | 17 | format.precision := 3 18 | 19 | print((123456)<~format) 20 | 21 | print((pi())<~(precision: 0, digits: 5, width:10)) 22 | 23 | print((1762354)<~(precision: 10, digits: 3, format:fmtExponent)) 24 | print((1762354)<~(precision: 10, digits: 3, format:fmtFixed)) 25 | print((1762354)<~(precision: 10, digits: 3, format:fmtGeneral)) 26 | print((1762354)<~(precision: 10, digits: 3, format:fmtNumber)) 27 | print((1762354)<~(precision: 10, digits: 3, format:fmtCurrency)) 28 | 29 | //print(7<~2) // tuple expected 30 | 31 | /* 32 | The argument is converted to a string using ffExponent or ffFixed 33 | format, depending on which one gives the shortest string. 34 | There will be no trailing zeroes. If Value is less than 0.00001 35 | or if the number of decimals left of the decimal point is larger 36 | than Precision then scientific notation is used, and Digits is 37 | the minimum number of digits in the exponent. Otherwise Digits is ignored. 38 | */ 39 | -------------------------------------------------------------------------------- /compiler/test/default.gear: -------------------------------------------------------------------------------- 1 | // testing the default variable functionality 2 | 3 | class Car is 4 | default _type := 'car' 5 | init(.type) for _type 6 | end 7 | 8 | var car := Car(type: 'Volvo') 9 | print(car) // Volvo 10 | 11 | car := 'Mercedes' 12 | print(car) 13 | 14 | //car := 12345 //error: Incompatibe types in assignment -> "_type:String:=Number". 15 | 16 | var c := 'hello' 17 | //c := car 18 | print(c) 19 | 20 | -------------------------------------------------------------------------------- /compiler/test/default1.gear: -------------------------------------------------------------------------------- 1 | // testing default variable and indexer with getter + setter 2 | 3 | record String is 4 | default _value := '' 5 | init(value) for _value 6 | subscript[i](char) for _value[i], _value[i] := char 7 | end 8 | 9 | var string := String('0123456789abcdefghijklmnopqrstuvwxyz') 10 | 11 | print(string) 12 | 13 | print(string[10]) 14 | string[10] := "x" 15 | print(string) 16 | print(string[10]) 17 | 18 | string := 'Hello world!' 19 | print(string) 20 | string[10] := "x" 21 | print(string) 22 | 23 | var s := String() 24 | s := 'Even this is possible' 25 | print(s) 26 | 27 | -------------------------------------------------------------------------------- /compiler/test/defer.gear: -------------------------------------------------------------------------------- 1 | // test defer 2 | 3 | func test() do 4 | print('Hello World') 5 | defer print('Bye now!') 6 | print('Welcome dude!') 7 | defer do 8 | print('Let''s meet later') 9 | print('Or call me') 10 | end 11 | print('Please, sit down.') 12 | end 13 | 14 | 15 | test() 16 | 17 | -------------------------------------------------------------------------------- /compiler/test/defer2.gear: -------------------------------------------------------------------------------- 1 | func myFunc() do 2 | print('Step 2') 3 | defer do 4 | print('Step 3') 5 | end 6 | print('Step 4') 7 | end 8 | 9 | func test() do 10 | print('Step 1') 11 | defer do 12 | print('step a') 13 | myFunc() 14 | print('step b') 15 | end 16 | print('Step 5') 17 | end 18 | 19 | 20 | test() 21 | 22 | -------------------------------------------------------------------------------- /compiler/test/defer4.gear: -------------------------------------------------------------------------------- 1 | func process(.fileName) do 2 | 3 | let inputFile := fileOpen(fileName, forReading) 4 | defer do 5 | print('closing file...') 6 | fileClose(inputFile) 7 | print('...file closed') 8 | end 9 | 10 | ensure inputFile >= 0 else 11 | print('Error opening file "$(fileName)".') 12 | return nil 13 | end 14 | 15 | let fileSize := fileSeek(inputFile, 0, fromEnd) 16 | 17 | fileSeek(inputFile, 0, fromBeginning) 18 | 19 | let bytesRead := fileRead(inputFile) 20 | 21 | if length(bytesRead) < fileSize then 22 | print('Error reading file "$(fileName)".') 23 | return nil 24 | end 25 | 26 | return (.bytesRead, .fileSize) 27 | end 28 | 29 | print('Enter file name: ') 30 | let file := readln() 31 | let contents := process(fileName: file) 32 | print(contents?.bytesRead) 33 | 34 | let size := contents?.fileSize 35 | print('size: $(size)') 36 | 37 | -------------------------------------------------------------------------------- /compiler/test/defer5.gear: -------------------------------------------------------------------------------- 1 | //test defer 2 | 3 | func test() do 4 | var a := 1 5 | print('1') 6 | if a = 1 then 7 | print('a') 8 | defer print('c') 9 | print('b') 10 | end 11 | print('2') 12 | defer print('3') 13 | print('4') 14 | end 15 | 16 | test() 17 | 18 | -------------------------------------------------------------------------------- /compiler/test/dict.gear: -------------------------------------------------------------------------------- 1 | // test dictionary 2 | 3 | var d := [1:'one', 2:'two', 3:'three'] 4 | 5 | print(d) 6 | print(d[1]) 7 | print(d[2]) 8 | print(d[3]) 9 | //print(d[4]) 10 | 11 | d[1] := 'twenty' 12 | print(d) 13 | 14 | 15 | -------------------------------------------------------------------------------- /compiler/test/dict05.gear: -------------------------------------------------------------------------------- 1 | 2 | let words := [ 3 | 'oma': 'grandmother', 4 | 'moeder': 'mother', 5 | 'vader': 'father', 6 | 'zuster': 'sister', 7 | 'zoon': 'son'] 8 | 9 | print(words['vader']) 10 | 11 | print(words['zoon'] ?? 'key not found') 12 | print(words['dochter'] ?? 'key not found') 13 | 14 | -------------------------------------------------------------------------------- /compiler/test/dict1.gear: -------------------------------------------------------------------------------- 1 | 2 | let dict := [1:'One', 2:'Two', 3:'Three', 4:'Four'] 3 | 4 | var x := [ x.value for x in dict where x.key%2=0 ] 5 | print(x) // [Two, Four] 6 | print(dict.keys) 7 | 8 | let words := [ 9 | 'pair':'couple', 10 | 'oma':'grandmother', 11 | 'man':'male', 12 | 'woman':'female'] 13 | 14 | let w := {word.value for word in words where word.key > 'oma' } 15 | print(w) 16 | 17 | // {couple, female} 18 | 19 | -------------------------------------------------------------------------------- /compiler/test/dict3.gear: -------------------------------------------------------------------------------- 1 | 2 | let milesToPoint := ['Point1':120.0 ,'Point2':50, 'Point3':70] 3 | 4 | var km := [ miles.value*1.6093 for miles in milesToPoint ] 5 | print('km to points: ', km) 6 | 7 | -------------------------------------------------------------------------------- /compiler/test/dict5.gear: -------------------------------------------------------------------------------- 1 | 2 | let milesToPoint := ['point1':120.0,'point2':50.0,'point3':70.0] 3 | 4 | let a := [234,346,4567,6789] 5 | print(a) 6 | print(length(a)) 7 | print(a.count) 8 | print(a.map(x=>x*2)) 9 | 10 | let x := milesToPoint.keys 11 | print(x) 12 | print(length(x)) 13 | print(x.count) 14 | 15 | let y := milesToPoint.values 16 | print(y) 17 | print(length(y)) 18 | print(y.count) 19 | print(y.map(x=>x*1.6093)) 20 | 21 | print(5+1.23456) 22 | 23 | let z := milesToPoint.values.map(t=>t*1.6) 24 | print(z) 25 | 26 | print('hello') 27 | let kmToPoint := milesToPoint.values.map(miles=>miles*1.6093 ) 28 | print(kmToPoint) 29 | 30 | print(pi()) 31 | 32 | -------------------------------------------------------------------------------- /compiler/test/dictio.gear: -------------------------------------------------------------------------------- 1 | 2 | let interestingNumbers := 3 | ['Prime': [1,2,3,5,7,11,13,17,19,23], 4 | 'Fibonacci': [1,1,2,3,5,8,13,21,34], 5 | 'Square': [1,4,9,16,25] 6 | ] 7 | 8 | for var pair in interestingNumbers do 9 | print(pair.key, ': ', pair.value) 10 | end 11 | 12 | print(interestingNumbers) 13 | 14 | var largest := 0 15 | 16 | for var type in interestingNumbers do 17 | for var number in type.value do 18 | if number > largest then 19 | largest := number 20 | end 21 | end 22 | end 23 | 24 | print('Largest number is $(largest)') 25 | 26 | -------------------------------------------------------------------------------- /compiler/test/dictionary.gear: -------------------------------------------------------------------------------- 1 | 2 | var smileys := ['smile': '😀', 'saint': '😇'] 3 | smileys.add(key: 'lol', value: '🤣') 4 | smileys.add(key: 'cool', value: '😎') 5 | smileys.add(key: 'cry', value: '😭') 6 | print(smileys) 7 | print(smileys.count) 8 | 9 | let keyAvailable := smileys.contains(key: 'lol') // true 10 | let smileyAvailable := smileys.contains(value: '😭') // true 11 | print(smileyAvailable) 12 | print(keyAvailable) 13 | 14 | print(smileys.keys) 15 | print(smileys.values) 16 | 17 | smileys.delete(key: 'lol') 18 | print(smileys) 19 | print(smileys.count) 20 | 21 | smileys.clear() 22 | print(smileys) 23 | print(smileys.count) 24 | 25 | -------------------------------------------------------------------------------- /compiler/test/ensure.gear: -------------------------------------------------------------------------------- 1 | let max := 100 2 | randomize() 3 | var number := random(max) + 1 4 | 5 | while true do 6 | print('Guess a number (1 to $(max)): ', terminator: '') 7 | 8 | ensure let guess := numberOf(readln()) where guess <> nil else 9 | print('That''s not a number!') 10 | continue 11 | end 12 | 13 | ensure (guess > 0) and (guess <= max) else 14 | print('That number is not in range 1 to ', max) 15 | continue 16 | end 17 | 18 | if guess < number then 19 | print('Too low.') 20 | elseif guess = number then 21 | print('You win!') 22 | break 23 | else 24 | print('Too high.') 25 | end 26 | end 27 | 28 | -------------------------------------------------------------------------------- /compiler/test/enum.gear: -------------------------------------------------------------------------------- 1 | 2 | enum Color is 3 | Red, Blue, Yellow, Green, Orange, Purple 4 | end 5 | 6 | var myColor := Color.Blue 7 | print(myColor.name) // prints ‘Blue’ 8 | 9 | 10 | enum TokenType is 11 | Plus='+', Min='-', Mul='*', Div='/', Rem='%' 12 | end 13 | var tokenType := TokenType.Mul 14 | print(tokenType.name) // prints ‘Mul’ 15 | print(tokenType.value) // prints ‘*’ 16 | 17 | -------------------------------------------------------------------------------- /compiler/test/enum1.gear: -------------------------------------------------------------------------------- 1 | // enumeration 2 | 3 | /* 4 | enum Math is 5 | Add = '+', Min = '-', Mul = '*', Div = '/' 6 | end 7 | 8 | var add := Math.Add 9 | print(add) 10 | print(add.name) 11 | print(add.value) 12 | */ 13 | use math 14 | 15 | record RGB is 16 | var red := 0, green := 0, blue := 0 17 | init(r,g,b) for self.red, self.green, self.blue 18 | func toString() => '$(self.red)-$(self.green)-$(self.blue)' 19 | val asHex do 20 | return dec2hex(self.red) + dec2hex(self.green) + dec2hex(self.blue) 21 | end 22 | end 23 | 24 | enum Color is 25 | Black = RGB(0,0,0), 26 | White = RGB(255,255,255), 27 | Red = RGB(255,0,0), 28 | Green = RGB(0,255,0), 29 | Blue = RGB(0,0,255), 30 | Yellow = RGB(255,255,0), 31 | Orange = RGB(255,128,0), 32 | Purple = RGB(127,0,255) 33 | 34 | func toString() => '$(self.name)' 35 | func valueToString() => self.value.toString() 36 | end 37 | 38 | var color := Color.Orange 39 | //var color := Color.Exit // expected Enum value 40 | print(color) 41 | print('color name: $(color.name)') 42 | print('color.value: $(color.value)') 43 | print('color.value as hex: $(color.value.asHex)') 44 | 45 | switch color 46 | case .Exit: print('exit') 47 | case .Black: print('Black: $(color.value.asHex)') 48 | case .White: print('White: $(color.value.asHex)') 49 | case .Red: print('Red: $(color.value.asHex)') 50 | case .Green: print('Green: $(color.value.asHex)') 51 | case .Blue: print('Blue: $(color.value.asHex)') 52 | case .Yellow: print('Yellow: $(color.value.asHex)') 53 | case .Orange: print('Orange: $(color.value.asHex)') 54 | case .Purple: print('Purple: $(color.value.asHex)') 55 | default: print('no color') 56 | end 57 | 58 | 59 | 60 | //add := color // error incompatible types 61 | 62 | class Class is 63 | var field := 0 64 | init(field) for self.field 65 | end 66 | 67 | var instance := Class(42) 68 | 69 | //var new := Class.field // error undefined static func 70 | 71 | -------------------------------------------------------------------------------- /compiler/test/enum2.gear: -------------------------------------------------------------------------------- 1 | enum Math is 2 | Add = '+', Min = '-', Mul = '*', Div = '/' 3 | val asStr := self.value 4 | end 5 | 6 | var calc := Math.Div 7 | print(calc.asStr) 8 | 9 | // type is derived from calc: Math 10 | switch calc 11 | case .Add: 12 | print('added') 13 | case .Min: 14 | print('subtracted') 15 | case .Mul: 16 | print('multiplied') 17 | case .Div: 18 | print('divided') // ! 19 | default: 20 | print('no math') 21 | end 22 | 23 | calc := Math.Mul 24 | 25 | switch calc 26 | case Math.Add: 27 | print('added') 28 | case Math.Min: 29 | print('subtracted') 30 | case Math.Mul: 31 | print('multiplied') // ! 32 | case Math.Div: 33 | print('divided') 34 | default: 35 | print('no math') 36 | end 37 | 38 | switch calc 39 | case 'a': print('a') 40 | case 'b': print('b') 41 | default: print('c') // ! 42 | end // c 43 | 44 | -------------------------------------------------------------------------------- /compiler/test/factorial.gear: -------------------------------------------------------------------------------- 1 | 2 | var factorial := /\n => (1..n).reduce(1, /\(x,y)=>x*y) // test 3 | print(factorial(69)) 4 | 5 | (1..10).each(/\(n) do 6 | print(n) 7 | end) 8 | 9 | print((1..10).map(x=>x^2)) 10 | 11 | -------------------------------------------------------------------------------- /compiler/test/fibonacci.gear: -------------------------------------------------------------------------------- 1 | // a Fibonacci generator 2 | 3 | /* 4 | The idea is to create a generator for Fibonacci numbers, such 5 | that you can write: 6 | 7 | for i in Fibonacci(15) do 8 | print(n, terminator: ' | ') 9 | end 10 | 11 | 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 | 34 | 55 | 89 | 144 | 233 | 377 | 610 | 12 | 13 | */ 14 | 15 | record Fibonacci is 16 | var max := 0 17 | init(max) for max 18 | end 19 | 20 | record FibonacciIterator is 21 | var _numbers := [] 22 | var _index := -1 23 | 24 | init(max) do 25 | if max >= 1 then 26 | _numbers.add(1) 27 | end 28 | if max >= 2 then 29 | _numbers.add(1) 30 | end 31 | for var i in 2..= 0 else 8 | print('Error opening file "$(fileName)".') 9 | fileClose(inputFile) 10 | return nil 11 | end 12 | 13 | let fileSize := fileSeek(inputFile, 0, fromEnd) 14 | 15 | fileSeek(inputFile, 0, fromBeginning) 16 | 17 | let bytesRead := fileRead(inputFile) 18 | 19 | if length(bytesRead) < fileSize then 20 | print('Error reading file "$(fileName)".') 21 | fileClose(inputFile) 22 | return nil 23 | end 24 | 25 | fileClose(inputFile) 26 | 27 | return (.bytesRead, .fileSize) 28 | end 29 | 30 | print('Enter file name: ') 31 | let file := readln() 32 | let contents := process(fileName: file) 33 | print(contents.bytesRead) 34 | 35 | let size := contents.fileSize 36 | print('size: $(size)') 37 | 38 | -------------------------------------------------------------------------------- /compiler/test/for2.gear: -------------------------------------------------------------------------------- 1 | 2 | // regular solution 3 | let len := 10 4 | for var i:=1 where i<=len, i+=1 do 5 | print(i^2, terminator: '|') 6 | end 7 | print() 8 | 9 | (1..len).each(/\(i) do 10 | print(i^2, terminator: '|') 11 | end) 12 | print() 13 | 14 | // using map on a range 15 | let numbers := (1..len).map(x=>x^2) 16 | numbers.each(/\(i) do 17 | print(i, terminator: '|') 18 | end) 19 | 20 | print() 21 | 22 | let numbers2 := 1..len 23 | numbers2.each(/\(i) do 24 | print(i^2, terminator: '|') 25 | end) 26 | 27 | print() 28 | 29 | // in one line 30 | (1..10).each(/\(i) do 31 | print(i^2, terminator: '|') 32 | end) 33 | 34 | print() 35 | 36 | // or 37 | (1..len).each(/\(i) do 38 | print(i^2, terminator: '|') 39 | end) 40 | print() 41 | 42 | (1..len).map(x=>x^2).each(/\(i) do 43 | print(i, terminator: '|') 44 | end) 45 | print() 46 | 47 | -------------------------------------------------------------------------------- /compiler/test/format.gear: -------------------------------------------------------------------------------- 1 | // testing formatting 2 | 3 | /* 4 | fmtGeneral = 1 5 | fmtExponent = 2 6 | fmtFixed = 3 7 | fmtNumber = 4 8 | fmtCurrency = 5 9 | */ 10 | 11 | print(510012.98<~(format: fmtCurrency, digits:2)) 12 | 13 | var number := pi() 14 | var format := (precision: 12, format: fmtGeneral) 15 | print(number<~format) 16 | 17 | format := (digits:2, format: fmtExponent) 18 | print(number<~format) 19 | format := (digits:5, width: 10) 20 | print(number<~format) 21 | 22 | let Euro := (digits:2, format: fmtCurrency, currency: '€') 23 | print(number<~Euro) 24 | print(2.12345) 25 | let amount := 1199075.75 26 | print('amounts') 27 | print(amount) 28 | print(amount<~(format: fmtGeneral, digits:2, precision: 10)) 29 | print(amount<~(format: fmtExponent, digits:2, precision: 10)) 30 | print(amount<~(format: fmtFixed, digits:2, precision: 10)) 31 | print(amount<~(format: fmtNumber, digits:2, precision: 10)) 32 | print(amount<~(format: fmtCurrency, digits:2, precision: 10)) 33 | 34 | -------------------------------------------------------------------------------- /compiler/test/func1.gear: -------------------------------------------------------------------------------- 1 | 2 | //var f := func (a,b) => a+b// error cannot parse func 3 | var f := lambda (a,b) => a+b 4 | 5 | print(f(4,5)) 6 | let a := 999 7 | 8 | -------------------------------------------------------------------------------- /compiler/test/func2.gear: -------------------------------------------------------------------------------- 1 | func add2Numbers(a,b) => a+b 2 | func mul2Numbers(a,b) => a*b 3 | 4 | func calc(x, y, function) => function(x,y) 5 | 6 | var sum := calc(20, 22, add2Numbers) 7 | var product := calc(2, 21, mul2Numbers) 8 | print('Sum is: $(sum) and product is: $(product).') 9 | 10 | -------------------------------------------------------------------------------- /compiler/test/func3.gear: -------------------------------------------------------------------------------- 1 | func test(n) do 2 | if n = 2 then 3 | print('early exit') 4 | return 5 | end 6 | print('tested') 7 | end 8 | 9 | test(1) 10 | test(2) 11 | test(3) 12 | print(test(2)) 13 | 14 | (1..10).each(/\(x) do 15 | print('Number $(x) squared is: $(x^2).') 16 | end) 17 | 18 | 19 | -------------------------------------------------------------------------------- /compiler/test/gettersetter.gear: -------------------------------------------------------------------------------- 1 | // getter and setter 2 | 3 | class Vehicle is 4 | var _type := 'car' 5 | init(.type) for _type 6 | 7 | val type := _type // getter 8 | 9 | func set(.type) do // setter 10 | _type := type 11 | end 12 | 13 | func toString() => _type 14 | end 15 | 16 | var vehicle := Vehicle() 17 | print(vehicle.type) 18 | vehicle.set(type: 'truck') 19 | print(vehicle.type) 20 | 21 | class Car < Vehicle is 22 | var _brand := '' 23 | init(.type, .brand) do 24 | inherited(type) 25 | _brand := brand 26 | end 27 | 28 | val brand := _brand //getter 29 | func set(.brand) do //setter 30 | _brand := brand 31 | end 32 | 33 | func toString() do 34 | return inherited toString() + ' ' + _brand 35 | end 36 | end 37 | 38 | var car := Car(type: 'station wagon', brand: 'Volvo') 39 | print(car.type) 40 | print(car.brand) 41 | car.set(type: 'truck') 42 | car.set(brand: 'Scania') 43 | 44 | print(car.toString()) 45 | //print(car._type) 46 | //print(car._brand) 47 | 48 | -------------------------------------------------------------------------------- /compiler/test/guess.gear: -------------------------------------------------------------------------------- 1 | use math 2 | var number := random(between: 0, 100) + 1 3 | 4 | while true do 5 | print('Guess a number: ') 6 | 7 | ensure var guess := numberOf(readln()) where guess <> nil else 8 | print('That`s not a number!') 9 | continue 10 | end 11 | 12 | if guess < number then 13 | print('Too low.') 14 | elseif guess = number then 15 | print('You win!') 16 | break 17 | else 18 | print('Too high.') 19 | end 20 | end 21 | 22 | -------------------------------------------------------------------------------- /compiler/test/hanoi.gear: -------------------------------------------------------------------------------- 1 | // towers of Hanoi problem 2 | 3 | func tower(diskNumbers, source, auxilary, destination) do 4 | if diskNumbers = 1 then 5 | print('$(source) \t-> $(destination)') 6 | else 7 | tower(diskNumbers-1, source, destination, auxilary) 8 | print('$(source) \t-> $(destination)') 9 | tower(diskNumbers-1, auxilary, source, destination) 10 | end 11 | end 12 | 13 | tower(7, 'src ', 'aux ', 'dest') 14 | 15 | 16 | -------------------------------------------------------------------------------- /compiler/test/hex.gear: -------------------------------------------------------------------------------- 1 | // hexadecimals and characters 2 | 3 | let n := 0x9F 4 | print(n) // 159 5 | 6 | print(0x1F89A) // 129178 7 | //print(0x1aH) 8 | //print(0xH) 9 | 10 | print(0x1B) 11 | print(0b11011) 12 | print(0o33) 13 | 14 | let c := #65 15 | print(c) // A 16 | 17 | let s := #240#159#166#129 18 | print(s) // 🦁 19 | 20 | let emoji := chr(240)+chr(159)+chr(166)+chr(129) 21 | print(emoji) 22 | 23 | print(chr(650)) // error 24 | 25 | -------------------------------------------------------------------------------- /compiler/test/hex2.gear: -------------------------------------------------------------------------------- 1 | 2 | func toHex(d) do 3 | let chars := '0123456789ABCDEF' 4 | var r := d % 16 5 | if d - r = 0 then 6 | return chars[r] 7 | end 8 | return toHex((d - r) / 16) + chars[r] 9 | end 10 | 11 | let x := 123455543 12 | print(toHex(x)) 13 | 14 | print(0x75BC837) // 123455543 15 | 16 | -------------------------------------------------------------------------------- /compiler/test/if.gear: -------------------------------------------------------------------------------- 1 | // test if statement 2 | 3 | //var a := 8 4 | 5 | if var a := 8 where a=10 then 6 | print(a) 7 | elseif a>10 then 8 | print('smth big') 9 | else 10 | print('smaller') 11 | end 12 | 13 | -------------------------------------------------------------------------------- /compiler/test/in.gear: -------------------------------------------------------------------------------- 1 | // test in 2 | 3 | var a := [1,2,3,4,5,6,7,8,9] 4 | 5 | ensure let x := 10 where x in a else 6 | print('nooo') 7 | end 8 | 9 | if 5 in a then 10 | print('yes') 11 | end 12 | 13 | 14 | let set := {4,4,4,5,6,6,7,8,9,9,3,2,4,5} // all duplicates removed 15 | 16 | print(set) 17 | print(5 in set) 18 | 19 | print({1,2}.union(with: {2, 3})) 20 | 21 | print(5 in (1..10).toArray()) 22 | 23 | let mySet := {x for x in 0..<100 where x^2>50 } 24 | print(mySet) 25 | 26 | -------------------------------------------------------------------------------- /compiler/test/indexed.gear: -------------------------------------------------------------------------------- 1 | 2 | record TimesTable is 3 | var multiplier := 1 4 | init(.multiplier) for self.multiplier 5 | subscript[i] for i * self.multiplier 6 | end 7 | 8 | let table := TimesTable(multiplier: 7) 9 | print('Table of $(table.multiplier):') 10 | for var index in 1..10 do 11 | print(index, ' * ', table.multiplier, ' = ',table[index]) 12 | end 13 | 14 | -------------------------------------------------------------------------------- /compiler/test/indexer.gear: -------------------------------------------------------------------------------- 1 | 2 | record List is 3 | default items := [] 4 | val count := length(self.items) 5 | func add(item) do 6 | self.items.add(item) 7 | end 8 | //subscript[i] for self.items[i] // only getter 9 | subscript[i](value) for self.items[i], self.items[i] := value 10 | // getter + setter 11 | end 12 | 13 | var list := List() 14 | list.add(3) 15 | list.add(5) 16 | list.add(7) 17 | list.add(11) 18 | 19 | 20 | let z := list[2] 21 | print(z) 22 | list[3] := 9 23 | print(list.items) 24 | print(list) 25 | 26 | -------------------------------------------------------------------------------- /compiler/test/inherit.gear: -------------------------------------------------------------------------------- 1 | // inherit 2 | 3 | class Circle is 4 | var radius := 0 5 | val area := pi() * self.radius^2 6 | init(.radius) do 7 | self.radius := radius 8 | end 9 | func set(.radius) do 10 | self.radius := radius 11 | //radius := radius 12 | end 13 | func set(.newRadius) do 14 | self.radius := newRadius 15 | end 16 | end 17 | 18 | class Cylinder < Circle is 19 | var height := 0 20 | val volume := self.area * self.height 21 | init(.radius, .height) do 22 | inherited (radius) 23 | self.height := height 24 | end 25 | func set(.height) do 26 | self.height := height 27 | //height := height 28 | end 29 | end 30 | 31 | var circle := Circle(radius:1) 32 | var cylinder := Cylinder(radius:2, height:10) 33 | 34 | 35 | print('area = $(circle.area<~(format: fmtGeneral, precision:4, digits:2)) m2') 36 | 37 | let format1 := (format: fmtFixed, precision:4, digits:2, width:8) 38 | let format2 := (format: fmtGeneral, precision:0, digits:0, width:5) 39 | 40 | circle.set(radius:2) 41 | print(circle.area<~format1) 42 | print(cylinder.area<~format1) 43 | print(cylinder.height<~format2) 44 | print(cylinder.volume<~format1) 45 | print(cylinder.radius<~format2) 46 | cylinder.set(radius:3) 47 | cylinder.set(height:8) 48 | print(cylinder.volume<~format1) 49 | print(3e10<~format2) 50 | 51 | let format3 := (format: fmtCurrency, 52 | currency: '€', precision:0, digits:2, width:10 53 | ) 54 | 55 | print(10.25<~format3) 56 | 57 | circle.set(newRadius: 10) 58 | print('radius = $(circle.radius)') 59 | /* 60 | //cylinder.set(1) 61 | cylinder.set(5) 62 | print(cylinder.volume) 63 | */ 64 | 65 | //circle.area := 3 // error immutable 66 | 67 | -------------------------------------------------------------------------------- /compiler/test/inherit1.gear: -------------------------------------------------------------------------------- 1 | class Bar is 2 | var f := 0 3 | init(.f) for f 4 | end 5 | 6 | class Baz '$(self.code)' 9 | end 10 | 11 | var num1 := Number(10) 12 | var num2 := Number(20) 13 | 14 | print(num1.toString()) 15 | print(num2.toString()) 16 | 17 | num1.write() 18 | num2.write() 19 | 20 | ensure num1 is Number else 21 | print(num1.toString, ' is not a number.') 22 | end 23 | 24 | class Test is 25 | var x := 'abc' 26 | func toString() => self.x 27 | end 28 | 29 | ensure var t := Test() where t is Number else 30 | print('$(t) is not a Number.') 31 | end 32 | 33 | -------------------------------------------------------------------------------- /compiler/test/lambda.gear: -------------------------------------------------------------------------------- 1 | //use system 2 | 3 | func calc(times n, function) do 4 | //while var k:=1 where k<=n for k+=1 do 5 | for var k in 1..n do 6 | print(function(k)<~(width:5), terminator: ' ') 7 | end 8 | print() 9 | end 10 | 11 | calc(times: 5, x=>x) // 1 2 3 4 5 12 | calc(times: 5, x=>x^2) // 1 4 9 16 25 13 | calc(times: 5, x=>x^3) // 1 8 27 64 125 14 | calc(times: 5, x=>x^4) // 1 16 81 256 625 15 | calc(times: 5, x=>x^5) // 1 32 243 1024 3125 16 | calc(times: 5, x=>x^6) // 1 64 729 4096 15625 17 | print() 18 | 19 | // calculate the integral over a function over a range in n steps 20 | 21 | func integral(f, from a, to b, steps n) do 22 | var sum := 0 23 | let dt := (b-a)/n 24 | for var i := 0 where isqrt(1-x^2), from: -1, to: 1, steps: 100000)) 31 | print(pi()/2) 32 | 33 | -------------------------------------------------------------------------------- /compiler/test/lambda2.gear: -------------------------------------------------------------------------------- 1 | 2 | var numbers := [1,2,3,4,5,6,7,8,9,10] 3 | numbers.each( 4 | lambda(x) do 5 | let squared := x^2 6 | print('Number $(x) squared is: $(squared).') 7 | end) 8 | 9 | let squaredNumbers := numbers.map(x=>x^2) 10 | print(squaredNumbers) 11 | 12 | let evenNumbers := numbers.filter(x=>x%2=0) 13 | print(evenNumbers) 14 | 15 | let sum := numbers.reduce(0, /\(x,y)=>x+y) 16 | print(sum) // 55 17 | let factorial := numbers.reduce(1, /\(x,y)=>x*y) 18 | print(factorial) // 3628800 19 | 20 | -------------------------------------------------------------------------------- /compiler/test/list.gear: -------------------------------------------------------------------------------- 1 | // linked list 2 | 3 | record List is 4 | var data := nil, next := nil 5 | init(data, next) for self.data, self.next 6 | 7 | func map(function) do 8 | var data := function(self.data) 9 | var next := nil 10 | if self.next<>nil then 11 | next := self.next.map(function) 12 | end 13 | return List(data, next) 14 | end 15 | 16 | func display () do 17 | var list := self 18 | while list<>nil do 19 | print(list.data, terminator: "|") 20 | list := list.next 21 | end 22 | print() 23 | end 24 | 25 | end 26 | 27 | var list := List(1, List(2, List(3, List(4, nil)))) 28 | list.display() 29 | 30 | list := list.map(n=>n*2) 31 | list.display() 32 | 33 | -------------------------------------------------------------------------------- /compiler/test/list1.gear: -------------------------------------------------------------------------------- 1 | 2 | var list := [] 3 | 4 | list.add('1') 5 | list.add(2) 6 | list.add(value: true) 7 | 8 | print(list) 9 | list.insert(1, 'yes') 10 | print(list) 11 | list.insert(at:1, value:'right') 12 | print(list) 13 | 14 | print(list.contains(2)) 15 | print(list.contains(value:3)) 16 | //list.insert('a', 'No') // Error: Index must be a number. 17 | 18 | let i := list.indexOf(2) 19 | print(i) 20 | print(list.index(of: true)) 21 | print(list.index(of: 'hello')) // -1 22 | 23 | let a := list.add(array: ['x','y','z']) 24 | print(a) 25 | let b := list.add(value: ['x','y','z']) 26 | print(b) 27 | 28 | list.delete(index:2) 29 | print(list) 30 | //list.delete(index:23) // Error: Array index 23 out of range [0,8). 31 | 32 | list.remove(value: 'x') 33 | print(list) 34 | 35 | list.clear() 36 | print(list) 37 | 38 | let arr := [0,1,2,3,4,5] 39 | arr.swap(2,4) 40 | print(arr) 41 | //arr.swap(index1:2,index2:7) //Error: At least 1 Array index (2, 7) out of range 0..<6. 42 | //print(arr) 43 | 44 | arr.swap(index1:2,index2:4) 45 | print(arr) 46 | 47 | print('count: ', arr.count) 48 | 49 | let a1 := [1,2,3,4] 50 | let a2 := [1,2,3,4] 51 | print(a1=a2) 52 | print(not (a1=a2)) 53 | print(a1+a2) 54 | 55 | -------------------------------------------------------------------------------- /compiler/test/list2.gear: -------------------------------------------------------------------------------- 1 | let list := [1,2,3,4,5,6,7,8,9,10] 2 | 3 | list.add(11) 4 | 5 | for var i in list do 6 | print(i, terminator: '|') 7 | end 8 | print() 9 | 10 | -------------------------------------------------------------------------------- /compiler/test/listb.gear: -------------------------------------------------------------------------------- 1 | 2 | let list := [1,2,3,4,5,6] 3 | var r := [x^2 for x in list where x%2=0] 4 | 5 | print(r) 6 | 7 | print({x^3 for x in 1..10 where x%2=1}) 8 | 9 | let s := {1,2,3,4,5,6,7,8} 10 | print(s) 11 | print(s.first) 12 | print(s.head) 13 | print(s.last) 14 | print(s.tail) 15 | 16 | -------------------------------------------------------------------------------- /compiler/test/listcomp.gear: -------------------------------------------------------------------------------- 1 | //use system 2 | 3 | let num := [n for n in 0..100 where n%2=0 and n%5=0] 4 | print(num) 5 | 6 | let toggle := [if i%2=0 then 'even' else 'odd' for i in 0..10] 7 | print(toggle) 8 | 9 | 10 | let fb := [if n%3=0 and n%5=0 then 'fizzBuzz' else 11 | if n%3=0 then 'fizz' else 12 | if n%5=0 then 'buzz' else n 13 | for n in 1..30] 14 | 15 | print(fb) 16 | 17 | let matrix := [[1, 2], [3,4], [5,6], [7,8]] 18 | 19 | let transpose := [[row[i] for row in matrix] for i in 0..1] 20 | print (transpose) 21 | 22 | let matrix2 := [[1, 3, 5, 7], [2, 4, 6, 8]] 23 | let transpose2 := [[row[i] for row in matrix2] for i in 0..3] 24 | print (transpose2) 25 | 26 | 27 | -------------------------------------------------------------------------------- /compiler/test/listcomp1.gear: -------------------------------------------------------------------------------- 1 | 2 | func fizzBuzz(n) do 3 | if (n%3=0) and (n%5=0) then 4 | return 'fizzBuzz' 5 | elseif n%3=0 then 6 | return 'fizz' 7 | elseif n%5=0 then 8 | return 'buzz' 9 | else 10 | return n 11 | end 12 | end 13 | 14 | //var fb := [n for n in 1..100].map(fizzBuzz) 15 | var fb := (1..100).map(fizzBuzz) 16 | 17 | print(fb) 18 | 19 | -------------------------------------------------------------------------------- /compiler/test/listcomp2.gear: -------------------------------------------------------------------------------- 1 | 2 | var list := [1,2,3,4,5,6,7,8,9,10] 3 | 4 | for var item in list where item%2=0 do 5 | print(item, terminator: '|') 6 | end 7 | print() 8 | 9 | while var iter := list.iterator where iter.moveNext do 10 | var item := iter.current 11 | print(item, terminator: '|') 12 | end 13 | print() 14 | 15 | let a := [x^2 for x in list] 16 | print(a) 17 | 18 | var result := [] 19 | for var x in list do 20 | result.add(x^2) 21 | end 22 | print(result) 23 | 24 | let transform := x=>x^2 25 | let include := x=>x%2=0 26 | //let include := nil 27 | let builder := [] 28 | while var iter := list.iterator where iter.moveNext do 29 | var item := iter.current 30 | if ?include then 31 | builder.add(transform(item)) 32 | elseif include(item) then 33 | builder.add(transform(item)) 34 | end 35 | end 36 | 37 | print(builder) 38 | 39 | 40 | -------------------------------------------------------------------------------- /compiler/test/listcomp4.gear: -------------------------------------------------------------------------------- 1 | let matrix := [[1, 2], [3,4], [5,6], [7,8]] 2 | print(matrix) 3 | let transpose := [[row[i] for row in matrix] for i in 0..1] 4 | print (transpose) 5 | 6 | -------------------------------------------------------------------------------- /compiler/test/loop2.gear: -------------------------------------------------------------------------------- 1 | 2 | func factorial(n) do 3 | var result := 1 4 | loop var counter := n do 5 | result *= counter 6 | counter -=1 7 | exit when counter=0 8 | end 9 | return result 10 | end 11 | 12 | print(factorial(70)) 13 | 14 | -------------------------------------------------------------------------------- /compiler/test/loop3.gear: -------------------------------------------------------------------------------- 1 | 2 | randomize() 3 | 4 | loop 5 | var x := 0, y := 0 6 | do 7 | x := random(10) 8 | print('$(x) squared', terminator: ': ') 9 | exit when x = 0 10 | y := x^2 11 | print(y) 12 | exit when y > 70 13 | end 14 | 15 | -------------------------------------------------------------------------------- /compiler/test/loopnew.gear: -------------------------------------------------------------------------------- 1 | // new loop idea 2 | 3 | randomize() 4 | 5 | loop var x := 0 do 6 | x := random(10) 7 | exit when x = 0 8 | let y := x^2 9 | print(y) 10 | end 11 | 12 | print() 13 | 14 | /*randomize() 15 | 16 | loop do 17 | var z := random(10) 18 | exit when z = 0 else // 'z' unknown 19 | let y := z^2 // 'z' unknown 20 | print(y) 21 | end 22 | */ 23 | 24 | func factorial(n) do 25 | var result := 1 26 | loop var counter := n do 27 | result *= counter 28 | counter -=1 29 | exit when counter=0 30 | print(result) 31 | end 32 | return result 33 | end 34 | 35 | print(factorial(10)) 36 | 37 | func fac(n) do 38 | var result := 1 39 | loop var counter := 1 do 40 | result *= counter 41 | counter +=1 42 | exit when counter>n 43 | print(result) 44 | end 45 | return result 46 | end 47 | 48 | print(fac(10)) 49 | 50 | 51 | -------------------------------------------------------------------------------- /compiler/test/mandelbrot1.gear: -------------------------------------------------------------------------------- 1 | 2 | var yMin := -0.2, yMax := 0.1 3 | var xMin := -1.5, xMax := -1.1 4 | 5 | for var yPixel:=0 where yPixel<32, yPixel+=1 do 6 | var y := (yPixel / 24) * (yMax - yMin) + yMin 7 | for var xPixel:=0 where xPixel<80, xPixel+=1 do 8 | var x := (xPixel/79) * (xMax - xMin) + xMin 9 | var pixel := '' 10 | var x0 := x 11 | var y0 := y 12 | for var iter:=0 where iter<80, iter+=1 do 13 | var x1 := (x0 * x0) - (y0 * y0) 14 | var y1 := 2 * x0 * y0 15 | x1+=x 16 | y1+=y 17 | x0:=x1 18 | y0:=y1 19 | let d := (x0 * x0) + (y0 * y0) 20 | if d>4 then 21 | pixel := ' .:;+=xX$&'[floor(iter/8)] 22 | break 23 | end 24 | end 25 | print(pixel, terminator: '') 26 | end 27 | print() 28 | end 29 | 30 | -------------------------------------------------------------------------------- /compiler/test/map_alt.gear: -------------------------------------------------------------------------------- 1 | // alternative map, reduce, filter 2 | // using recursion 3 | 4 | extension Array is 5 | 6 | // f is a function in below routines 7 | 8 | func map(f) => 9 | match @count 10 | if 0: [] 11 | else [f(@head)] + @tail.map(f) 12 | 13 | func reduce(value, f) => 14 | match @count 15 | if 0: value 16 | else @tail.reduce(f(@head, value), f) 17 | 18 | func filter(pred) => // predicate function 19 | match @count 20 | if 0: [] 21 | else pred(@head)? 22 | true: [@head] + @tail.filter(pred) 23 | false: @tail.filter(pred) 24 | 25 | func each(f) do 26 | if @count <> 0 then 27 | f(@head) 28 | @tail.each(f) 29 | end 30 | end 31 | 32 | func flatMap(f) => @map(f).reduce([],/\(x,y)=>y+x) 33 | 34 | func reversed() => 35 | match @count 36 | if 0: [] 37 | else @tail.reversed() + [@head] 38 | 39 | func sum() => 40 | match @count 41 | if 0: 0 42 | else @head + @tail.sum() 43 | 44 | end 45 | 46 | func map(list, f) do 47 | if list.count = 0 then 48 | return [] 49 | end 50 | return [f(list.head)] + list.tail.map(f) 51 | end 52 | 53 | func reduce(list, f, initial) do 54 | if list.count = 0 then 55 | return initial 56 | end 57 | return reduce(list.tail, f, f(list.head, initial)) 58 | end 59 | 60 | func filter(list, pred) do 61 | if list.count = 0 then 62 | return [] 63 | end 64 | if pred(list.head) then 65 | return [list.head] + filter(list.tail, pred) 66 | end 67 | return filter(list.tail, pred) 68 | end 69 | 70 | 71 | 72 | 73 | var list := [1,2,3,4,5,6] 74 | print(list.map(x=>x^2)) 75 | print(map(list, x=>x^2)) 76 | 77 | print(list.reduce(0, /\(x,y)=>x+y)) 78 | print(list.reduce(1, /\(x,y)=>x*y)) 79 | print(reduce(list, /\(x,y)=>x+y, 0)) 80 | print(reduce(list, /\(x,y)=>x*y, 1)) 81 | 82 | print(filter(list, x=>x%2=0)) 83 | print(list.filter(x=>x%2<>0)) 84 | 85 | list.each(/\(x) do 86 | print(x) 87 | end) 88 | 89 | print(list.sum()) 90 | 91 | let square := x=> [x*x] 92 | print(square(5)) 93 | print([1,2,3].map(square)) 94 | print([1,2,3].flatMap(square)) 95 | 96 | print([1,2,3,4,5].reversed()) 97 | 98 | -------------------------------------------------------------------------------- /compiler/test/match.gear: -------------------------------------------------------------------------------- 1 | // test match expr 2 | 3 | var x := match 4 4 | if 1: 'one' 5 | if 2: 'two' 6 | if 3: 'three' 7 | if 4, 5, 6: 'whatever' + ' it takes' 8 | else 'none' 9 | 10 | print(x) 11 | 12 | // using if-expressiom 13 | func fact(n) => if n<=1 then 1 else n*fact(n-1) 14 | 15 | print(fact(10)) 16 | 17 | func factorial(n) => 18 | match n 19 | if 0: 1 20 | if 1: 1 21 | else n*factorial(n-1) 22 | 23 | print(factorial(10)) 24 | 25 | func fibonacci(n) => 26 | match n 27 | if 0: 0 28 | if 1: 1 29 | if 2: 1 30 | else fibonacci(n-1)+fibonacci(n-2) 31 | 32 | print(fibonacci(10)) 33 | 34 | // using if-expressiom 35 | func fib(n) => if n<=1 then n else fib(n-1)+fib(n-2) 36 | 37 | print(fib(10)) 38 | 39 | func fib2(n) => 40 | if n=0 then 0 41 | else if n=1 then 1 42 | else if n=2 then 1 43 | else fib2(n-1)+fib2(n-2) 44 | 45 | print(fib2(10)) 46 | 47 | func fibo(n) => n<=1? true: n false: fibo(n-1)+fibo(n-2) 48 | print(fibo(10)) 49 | 50 | -------------------------------------------------------------------------------- /compiler/test/match1.gear: -------------------------------------------------------------------------------- 1 | // match 2 | use system 3 | 4 | var x := match 10 5 | if 1: 'One' 6 | if in 2..8: 'More' 7 | if 9,10,11: 'Nine or higher' 8 | else 'twelve' 9 | 10 | print(x) 11 | 12 | let value := 10 13 | let z := match value 14 | if < 0: 'below zero' 15 | if in 0..<10: 'teenager' 16 | if in 10..20: 'in his twenties' 17 | if >= 21: 'that''s old' 18 | else 'wrong' 19 | 20 | print(z) 21 | 22 | //func fib(n) => if n<=1 then n else fib(n-1)+fib(n-2) 23 | 24 | func fib(n) => 25 | match n 26 | if <= 1: n 27 | else fib(n-1) + fib(n-2) 28 | 29 | print(fib(10)) 30 | 31 | let age := 35 32 | print( match age 33 | if < 0: 'undefined' 34 | if in 0..<10: 'child' 35 | if in 10..<20: 'teen' 36 | if in 30..<40: 'young adult' 37 | if in 40..<65: 'middle aged' 38 | else 'pensionado' 39 | ) 40 | 41 | 42 | -------------------------------------------------------------------------------- /compiler/test/match3.gear: -------------------------------------------------------------------------------- 1 | // match 2 | 3 | use system 4 | 5 | var someCharacter := 'u' 6 | print(someCharacter, match someCharacter 7 | if 'a', 'e', 'i', 'o', 'u' : ' is a vowel' 8 | if in {'b', 'c', 'd', 'f', 'g', 'h', 'j', 9 | 'k', 'l', 'm', 'n', 'p', 'q', 'r', 10 | 's', 't', 'v', 'w', 'x', 'y', 'z'} : ' is a consonant' 11 | else ' is not a vowel nor a consonant') 12 | 13 | let alphabet := (ord("a")..ord("z")).toSet().map(c=>chr(c)) 14 | let vowels := {"a", "e", "i", "o", "u"} 15 | //print(alphabet) 16 | 17 | let otherCharacter := "=" 18 | print(otherCharacter, match otherCharacter 19 | if in alphabet - vowels: ' is a consonant' 20 | if in vowels: ' is a vowel' 21 | else ' is not a vowel nor a consonant') 22 | 23 | 24 | -------------------------------------------------------------------------------- /compiler/test/match4.gear: -------------------------------------------------------------------------------- 1 | class Root is 2 | var name := 'Root' 3 | end 4 | 5 | class First < Root is 6 | end 7 | 8 | class Second < Root is 9 | end 10 | 11 | class Third < Second is 12 | end 13 | 14 | class Fourth is 15 | end 16 | 17 | var sec := Second() 18 | //var sec := Fourth() 19 | 20 | print(match sec 21 | if is Root: 'Root' 22 | if is First: 'First' 23 | if is Second: 'Second' 24 | if is Third: 'Third' 25 | else 'None of the above' 26 | ) 27 | 28 | -------------------------------------------------------------------------------- /compiler/test/matrix.gear: -------------------------------------------------------------------------------- 1 | 2 | use arrays 3 | 4 | extension Array is 5 | 6 | /* + is predefined 7 | infix +(other) do 8 | let result := [] 9 | result.add(array: self) 10 | result.add(array: other) 11 | return result 12 | end 13 | */ 14 | infix *(other) do 15 | let result := [] 16 | for var i:=0 where ix+y) 25 | end 26 | 27 | prefix -() do 28 | let result := [] 29 | for var i:=0 where i nil then 14 | print('NONNIL') 15 | end 16 | 17 | newWindow := nil 18 | print(newWindow?.caption) 19 | 20 | print( newWindow?.caption ?? 'Default caption' ) 21 | 22 | if newWindow = nil then 23 | print('NIL') 24 | end 25 | 26 | //print(newWindow.caption) 27 | 28 | func test() do 29 | var w := nil 30 | //w := Window() 31 | print(w.caption) // generates runtime error 32 | end 33 | 34 | test() 35 | 36 | -------------------------------------------------------------------------------- /compiler/test/number.gear: -------------------------------------------------------------------------------- 1 | use typeinfo 2 | 3 | record Number is 4 | default _value := 0 5 | val value := _value 6 | init(value) do 7 | if type(of: value) = Type.Number then 8 | _value := value 9 | else 10 | error('Number type expected.') 11 | end 12 | end 13 | end 14 | 15 | extension Number is 16 | infix *(other) => self._value * other.value 17 | end 18 | 19 | var n := Number() 20 | n := 99 21 | var m := Number(10) 22 | print(n) 23 | print(n*m) 24 | print(n*Number(99)) 25 | //print(n*10) 26 | 27 | print('ab'+'cd') 28 | 29 | var s := Number('Hello world!') 30 | 31 | -------------------------------------------------------------------------------- /compiler/test/overload.gear: -------------------------------------------------------------------------------- 1 | 2 | func stringOf(.number) do 3 | return '$(number)' 4 | end 5 | 6 | func stringOf(.boolean) do 7 | return '$(boolean)' 8 | end 9 | 10 | func stringOf(.char, .length) do 11 | var result := '' 12 | for var i := 0 where i < length, i+=1 do 13 | result += char 14 | end 15 | return result 16 | end 17 | 18 | var a := stringOf(number: pi()) 19 | print(a) 20 | 21 | var c := stringOf(char: '=', length: 10) 22 | print(c) 23 | 24 | var b := stringOf(boolean: not(true or false)) 25 | print(b) 26 | 27 | -------------------------------------------------------------------------------- /compiler/test/overload1.gear: -------------------------------------------------------------------------------- 1 | // overload with default parameter 2 | 3 | func counter(start, .step) do 4 | return start + step 5 | end 6 | 7 | func counter(start) do 8 | return counter(start, step: 1) 9 | end 10 | 11 | var begin := 4 12 | 13 | print(counter(begin)) 14 | print(counter(begin, step: 5)) 15 | print(counter(begin)) 16 | 17 | -------------------------------------------------------------------------------- /compiler/test/people.gear: -------------------------------------------------------------------------------- 1 | use person 2 | 3 | var people := [ 4 | Person(name: 'Jerry', address: 'Milano, Italy', age: 39, income: 73000, 5 | cars: ['Opel Astra', 'Citroen C1']), 6 | Person(name: 'Cathy', address: 'Berlin, Germany', age: 34, income: 75000, 7 | cars: ['Audi A3']), 8 | Person(name: 'Bill', address: 'Brussels, Belgium', age: 48, income: 89000, 9 | cars: ['Volco XC60', 'Mercedes B', 'Smart 4x4']), 10 | Person(name: 'Francois', address: 'Lille, France', age: 56, income: 112000, 11 | cars: ['Volco XC90', 'Jaguar X-type']), 12 | Person(name: 'Joshua', address: 'Madrid, Spain', age: 43, income: 42000, 13 | cars: []) 14 | ] 15 | 16 | let names := people.map(/\person=>person.name) 17 | let totalIncome := people.map(/\person=>person.income).reduce(0, /\(x,y)=>x+y) 18 | let allCars := people.flatMap(/\person=>person.cars) 19 | 20 | print(names) 21 | print(totalIncome) 22 | print(allCars) 23 | 24 | -------------------------------------------------------------------------------- /compiler/test/person.gear: -------------------------------------------------------------------------------- 1 | class Person is 2 | var name := '' 3 | var address := '' 4 | var age := 0 5 | var income := 0 6 | var cars := [] 7 | 8 | init(.name, .address, .age, .income, .cars) do 9 | self.name := name 10 | self.address := address 11 | self.age := age 12 | self.income := income 13 | self.cars := cars 14 | end 15 | end 16 | 17 | -------------------------------------------------------------------------------- /compiler/test/point.gear: -------------------------------------------------------------------------------- 1 | // testing overloading functions 2 | record Point is 3 | var x:=0, y:=0 4 | init(.x, .y) for self.x, self.y 5 | 6 | func distance(to point) do 7 | return sqrt((point.x-self.x)^2 + (point.y-self.y)^2) 8 | end 9 | end 10 | 11 | var p0 := Point(x:0,y:0), p1 := Point(x:1,y:1), p2 := Point(x:3,y:4) 12 | 13 | print(p1.distance(to: p0)) 14 | print(p2.distance(to: p0)) 15 | 16 | extension Point is 17 | func set(.x) do 18 | self.x := x 19 | end 20 | func set(.y) do 21 | self.y := y 22 | end 23 | func set(.x,.y) do 24 | self.x := x 25 | self.y := y 26 | end 27 | end 28 | 29 | p0.set(x:3) 30 | p0.set(y:4) 31 | 32 | print(p1.distance(to: p0)) 33 | print(p2.distance(to: p0)) 34 | 35 | p0.set(x:8,y:10) 36 | print(p1.distance(to: p0)) 37 | print(p2.distance(to: p0)) 38 | 39 | -------------------------------------------------------------------------------- /compiler/test/point1.gear: -------------------------------------------------------------------------------- 1 | record Point is 2 | var x := 0, y := 0 3 | init(x, y) for self.x, self.y 4 | 5 | val origin := Point(0,0) 6 | 7 | func distance(to other) do 8 | let dx := self.x - other.x 9 | let dy := self.y - other.y 10 | return sqrt(dx*dx + dy*dy) 11 | end 12 | 13 | val magnitude := sqrt(self.x^2 + self.y^2) 14 | end 15 | 16 | extension Point is 17 | infix +(other) => Point(self.x + other.x, self.y+other.y) 18 | end 19 | 20 | var p1 := Point(12,16) 21 | let o := Point().origin 22 | var distance := p1.distance(to: o) 23 | print(distance) 24 | 25 | var p2 := p1 + Point(3,4) 26 | print(p2.distance(to: o)) 27 | print(p2.magnitude) 28 | 29 | -------------------------------------------------------------------------------- /compiler/test/primes0.gear: -------------------------------------------------------------------------------- 1 | 2 | func isPrime(number) do 3 | let sqrtNum := sqrt(number) 4 | for var i:=3 where i<= sqrtNum, i+=2 do 5 | if number%i = 0 then 6 | return false 7 | end 8 | end 9 | return true 10 | end 11 | 12 | var m := milliseconds() 13 | 14 | let primes := [2] + 15 | [n for n in (3..<10000).step(by:2) where isPrime(n)] 16 | 17 | 18 | var ms := milliseconds() - m 19 | print('In $(ms) ms.') 20 | 21 | 22 | print(primes.count) 23 | 24 | -------------------------------------------------------------------------------- /compiler/test/primes01.gear: -------------------------------------------------------------------------------- 1 | 2 | let m1 := milliseconds() 3 | 4 | func isPrime(number) do 5 | let sqrtNum := sqrt(number) 6 | for var i in (3..sqrtNum).step(by:2) where number%i = 0 do 7 | return false 8 | end 9 | return true 10 | end 11 | 12 | //var primes := (3..<10000).step(by:2).filter(n=>isPrime(n)) 13 | let primes := [n for n in (3..<10000).step(by:2) where isPrime(n)] 14 | 15 | print(milliseconds()-m1) 16 | 17 | print(primes.count) 18 | 19 | 20 | -------------------------------------------------------------------------------- /compiler/test/primes3.gear: -------------------------------------------------------------------------------- 1 | 2 | func isPrime(number) do 3 | let sqrtNum := sqrt(number) 4 | for var i:=3 where i<= sqrtNum, i+=2 do 5 | if number%i = 0 then 6 | return false 7 | end 8 | end 9 | return true 10 | end 11 | 12 | var m := milliseconds() 13 | 14 | let primes := [2] + 15 | [n for n in (3..<10000).step(by:2) where isPrime(n)] 16 | 17 | 18 | var ms := milliseconds() - m 19 | print('In $(ms) ms.') 20 | 21 | 22 | print(primes.count) 23 | 24 | m := milliseconds() 25 | 26 | var primes2 := [2] + (3..<10000).step(by:2).filter( 27 | lambda(number) do 28 | let sqrtNum := sqrt(number) 29 | for var i:=3 where i<= sqrtNum, i+=2 do 30 | if number%i = 0 then 31 | return false 32 | end 33 | end 34 | return true 35 | end) 36 | 37 | ms := milliseconds() - m 38 | print('In $(ms) ms.') 39 | 40 | print(primes2.count) 41 | 42 | m := milliseconds() 43 | 44 | var primes3 := [2] + (3..<10000).step(by:2).filter( 45 | lambda(number) do 46 | for var i in (3..sqrt(number)).step(2) do 47 | if number%i = 0 then 48 | return false 49 | end 50 | end 51 | return true 52 | end) 53 | 54 | ms := milliseconds() - m 55 | print('In $(ms) ms.') 56 | 57 | print(primes3.count) 58 | 59 | /* 60 | In 16 ms. 61 | 1229 62 | In 15 ms. 63 | 1229 64 | In 36 ms. 65 | 1229 66 | 67 | for..in is roughly twice as slow 68 | */ 69 | -------------------------------------------------------------------------------- /compiler/test/private.gear: -------------------------------------------------------------------------------- 1 | // private 2 | 3 | record Test is 4 | default _field := 0 5 | 6 | let data := 42 7 | var nonsense := -999999 8 | 9 | val field := _field 10 | func set(.field) do 11 | _field := field 12 | self.nonsense := field*2 13 | end 14 | 15 | func _help() do 16 | return '$(self.data)' 17 | end 18 | 19 | func toString() => self._help() 20 | end 21 | 22 | var test := Test() 23 | test.set(field: 99) 24 | 25 | print(test) 26 | print(test.field) 27 | //print(test._field) // error cannot access private field 28 | 29 | //test._field := 100 // error cannot access private field 30 | 31 | print(test.data) 32 | //test.data := 43 // error cannot assign value to constant 33 | 34 | print(test.nonsense) 35 | test.nonsense += -1 36 | print(test.nonsense) 37 | print(test.toString()) 38 | //print(test._help()) 39 | 40 | -------------------------------------------------------------------------------- /compiler/test/private2.gear: -------------------------------------------------------------------------------- 1 | // private fields and using a getter and setter 2 | // private fields don't require 'self' in front of it 3 | // so, either 'self._type' or '_type' are ok to use 4 | // this is only for private fields 5 | 6 | class Building is 7 | var _type := 'Flat' 8 | 9 | val type := _type // getter 10 | func set(.type) do // setter 11 | _type := type 12 | end 13 | 14 | init(.type) for _type 15 | end 16 | 17 | var building := Building(type: 'Appartment') 18 | print(building.type) 19 | building.set(type: 'Office') 20 | print(building.type) 21 | 22 | -------------------------------------------------------------------------------- /compiler/test/question.gear: -------------------------------------------------------------------------------- 1 | // test on assigned = non nil 2 | 3 | var a := 3 4 | 5 | if assigned(a) then 6 | print('assigned') 7 | else 8 | print('nil') 9 | end 10 | 11 | a := nil 12 | if ?a then 13 | print('nil') 14 | else 15 | print('assigned') 16 | end 17 | 18 | -------------------------------------------------------------------------------- /compiler/test/range.gear: -------------------------------------------------------------------------------- 1 | 2 | 3 | for var item in (0..30).step(by:3) do 4 | print(item, terminator: '|') 5 | end 6 | print() 7 | 8 | for var number in 3..8 do 9 | print(number^2, terminator: '|') 10 | end 11 | print() 12 | 13 | var result := (1..100).filter(x=>x^2>3).map(x=>2*x) 14 | print(result) 15 | 16 | print((1..20).toArray()) 17 | 18 | 19 | print((0..<10).toArray()) 20 | var r := (1..10).filter(/\x=>x%2=0).map(/\x=>x^2) 21 | print(r) 22 | 23 | for var number in (1..20).filter(/\x=>x%2=0).map(/\x=>x^2) do 24 | print(number) 25 | end 26 | 27 | 28 | -------------------------------------------------------------------------------- /compiler/test/readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /compiler/test/repeat.gear: -------------------------------------------------------------------------------- 1 | // test repeating loop 2 | 3 | var x := 9 4 | do 5 | print(x, terminator: '|') 6 | x-=1 7 | end while x>=0 8 | print() 9 | print('x=',x) 10 | 11 | 12 | var y:=0 13 | var done := false 14 | do 15 | print(y, terminator: '|') 16 | y+=1 17 | done := y=10 18 | end while not done 19 | 20 | print() 21 | 22 | loop var y:=0, done := false do 23 | print(y, terminator: '|') 24 | y+=1 25 | done := y=10 26 | exit when done 27 | end 28 | 29 | 30 | -------------------------------------------------------------------------------- /compiler/test/satisfy.gear: -------------------------------------------------------------------------------- 1 | 2 | 3 | extension Array is 4 | func allSatisfy(predicate) do 5 | for var item in self where not predicate(item) do 6 | return false 7 | end 8 | return true 9 | end 10 | end 11 | 12 | let numbers := [1,0,0,3,6, -9] 13 | let allPositives := numbers.allSatisfy(x=>x>=0) 14 | 15 | print(allPositives) 16 | 17 | -------------------------------------------------------------------------------- /compiler/test/scores.gear: -------------------------------------------------------------------------------- 1 | 2 | let scores := [8.3, 7.7, 9.0, 5.4, 1,2] 3 | var sum := 0 4 | for var score in scores do 5 | sum += score 6 | end 7 | 8 | if let average := sum / scores.count where average > 6.0 then 9 | print('You passed!') 10 | elseif average>5.0 and average<=6.0 then 11 | print('You need to work harder!') 12 | else 13 | print('You failed!') 14 | end 15 | 16 | /* 17 | let scores := [8.3, 7.7, 9.0, 5.4] 18 | var sum := 0 19 | for var score in scores do 20 | sum += score 21 | end 22 | let average := sum / scores.count 23 | 24 | if average > 6.0 then 25 | print('You passed!') 26 | elseif (average>5.0) & (average<=6.0) then 27 | print('You need to work harder!') 28 | else 29 | print('You failed!') 30 | end 31 | */ 32 | 33 | /* 34 | let scores := ['History': 8.3, 'Science': 7.7, 'English': 9.0, 'Economy': 5.4] 35 | var sum := 0 36 | for each score in scores do 37 | sum += score.value 38 | print('Your $(score.key) result was $(score.value)') 39 | end 40 | let average := sum / scores.count 41 | print('The average is $(average)') 42 | */ 43 | -------------------------------------------------------------------------------- /compiler/test/sequence.gear: -------------------------------------------------------------------------------- 1 | 2 | 3 | var list := [1,2,3,4,5,6,7,8,9,10] 4 | 5 | print(list.map(x=>x^2)) 6 | 7 | print([x for x in list]) 8 | print([x^2 for x in list where x%2=0]) 9 | 10 | for var i in list do 11 | print(i) 12 | end 13 | 14 | 15 | print([x^2 for x in (1..10).toArray() where x%2=0]) 16 | 17 | var b := {1,2,3,4,5,6,7,8,9,10} 18 | print(b.map(x=>x^2)) 19 | 20 | 21 | -------------------------------------------------------------------------------- /compiler/test/set.gear: -------------------------------------------------------------------------------- 1 | // test sets 2 | 3 | let aSet := {1,1,2,3,5,5,8,13,21,8} 4 | print(aSet) 5 | print(aSet.contains(value: 7)) 6 | print(8 in aSet) 7 | 8 | var set := {1,2,3,4,5} 9 | 10 | print(set) 11 | 12 | let s := {} 13 | print(s) 14 | 15 | /* 16 | for item in set do 17 | print(item) 18 | end 19 | */ 20 | 21 | var a := {3,4,5,6,7,8} 22 | var b := {6,7,8,9,10,11} 23 | 24 | print('a: $(a)') 25 | print('b: $(b)') 26 | 27 | print('union of a and b: ', a.union(with: b)) 28 | 29 | print('intersection of a and b: ', a.intersect(with: b)) 30 | 31 | print('a exceptWith b: ', a.except(with: b)) 32 | 33 | print('a symmetricExceptWith b: ', a.symmetricExcept(with: b)) 34 | 35 | 36 | let x := {'a','b','c','d','e'} 37 | let y := {'p','q','r','s','t', 'u', 'v'} 38 | print(x) 39 | print(y) 40 | print('union of x and y: ', x.union(with: y)) 41 | 42 | print('d' in x) 43 | print('x' in x) 44 | 45 | -------------------------------------------------------------------------------- /compiler/test/set1.gear: -------------------------------------------------------------------------------- 1 | 2 | //use system 3 | 4 | var a := {3,4,5,6,7,8} 5 | var b := {6,7,8,9,10,11} 6 | 7 | print('a: $(a)') 8 | print('b: $(b)') 9 | 10 | print('union of a and b: ', a.union(with: b)) 11 | print('+ of a and b: ', a+b) 12 | 13 | print('intersection of a and b: ', a.intersect(with: b)) 14 | print('* of a and b: ', a*b) 15 | 16 | print('a exceptWith b: ', a.except(with: b)) 17 | print('a - b: ', a-b) 18 | 19 | print('a symmetricExceptWith b: ', a.symmetricExcept(with: b)) 20 | print('a ~ b: ', a~b) 21 | 22 | print(10 in (a~b)) 23 | 24 | print(a.toArray()) 25 | 26 | for var i in a do 27 | print(i) 28 | end 29 | print(b.toArray()) 30 | for var i in b do 31 | print(i) 32 | end 33 | 34 | -------------------------------------------------------------------------------- /compiler/test/set2.gear: -------------------------------------------------------------------------------- 1 | 2 | var set := {1,2,3,4,5,6,7,8,9} 3 | print(set.toArray()) 4 | for var i in set do 5 | print(i, terminator:' /') 6 | end 7 | print() 8 | 9 | print(set.map(x=>x^2)) 10 | 11 | var list := (1..15).toSet() 12 | print(list) 13 | for var i in list do 14 | print(i, terminator:' /' ) 15 | end 16 | print() 17 | 18 | var list2 := (1..15).toArray() 19 | print(list2) 20 | for var i in list2 do 21 | print(i, terminator:' /') 22 | end 23 | print() 24 | 25 | -------------------------------------------------------------------------------- /compiler/test/setbuilder.gear: -------------------------------------------------------------------------------- 1 | //test set builder 2 | 3 | var set := {n for n in 1..10} 4 | print(set) 5 | 6 | set := {n for n in 1..10 where n%2=0} 7 | print(set) 8 | 9 | // create set from array 10 | 11 | let set2 := {n for n in ['a','b','c','d','e','f','g']} 12 | print(set2) 13 | 14 | let set3 := {c for c in (ord('a')..ord('z')).map(/\n=>chr(n))} 15 | print(set3) 16 | 17 | let list := [c for c in (ord('a')..ord('z')).map(/\n=>chr(n))] 18 | print(list) 19 | 20 | for var item in {n for n in 1..10} do 21 | print(item) 22 | end 23 | 24 | -------------------------------------------------------------------------------- /compiler/test/smileys.gear: -------------------------------------------------------------------------------- 1 | 2 | var smileys := ['🤪', 'g', '🐶', '🐔', '🐵', '🦁', '🐯', '🐭', '🐱', '🐮', '🐷', 'ë', 'u'] 3 | 4 | for var smiley in smileys do 5 | print(smiley) 6 | end 7 | 8 | for var smiley in smileys do 9 | print(length(smiley)) 10 | for var i:=0 where i gear -x -f helloWorld.gear 10 | 11 | To print the AST: 12 | > gear -a -f helloWorld.gear 13 | 14 | It is important to copy the /gearlib folder, as it contains part of the RTL. Include 'use system' in your code to fully use the RTL. 15 | 16 | To create executables for Windows or Linux, compile the project with Lazarus/Free Pascal (v 3.04), in the respective OS. 17 | -------------------------------------------------------------------------------- /interpreter/doc/GearLang - An interpreter in Free Pascal - external visitor pattern.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdehaan2014/GearLanguage/04a861a8020a1a6a2c26e86896dac943d4655805/interpreter/doc/GearLang - An interpreter in Free Pascal - external visitor pattern.pdf -------------------------------------------------------------------------------- /interpreter/doc/The Gear language description.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jdehaan2014/GearLanguage/04a861a8020a1a6a2c26e86896dac943d4655805/interpreter/doc/The Gear language description.pdf -------------------------------------------------------------------------------- /interpreter/doc/readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /interpreter/examples/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /interpreter/examples/add.gear: -------------------------------------------------------------------------------- 1 | 2 | func add(a,b) => a+b 3 | 4 | print(add(7,9)) 5 | 6 | func sub(a,b) => a-b 7 | 8 | print(sub(9,7)) 9 | 10 | -------------------------------------------------------------------------------- /interpreter/examples/animals.gear: -------------------------------------------------------------------------------- 1 | // Implements the classic "Animals" guessing game. The user thinks of an animal. 2 | // The program asks a series of yes/no questions to try to guess the animal 3 | // they are thinking of. If the program fails, it asks the user for a new 4 | // question and adds the animal to its knowledge base. 5 | // 6 | // Internally, the program's brain is stored as a binary tree. Leaf nodes are 7 | // animals. Internal nodes are yes/no questions that choose which branch to 8 | // explore. 9 | 10 | class Node 11 | 12 | // Writes a prompt and reads a string of input. 13 | func promptString(prompt) 14 | print(prompt, terminator: '') 15 | return readln() 16 | end 17 | 18 | // Reads a "yes" or "no" (or something approximating) those and returns true 19 | // if yes was entered. 20 | func promptYesNo(prompt) 21 | while True do 22 | var line := self.promptString(prompt) 23 | 24 | if (line[0] = "y) | line[0] = "Y) then 25 | return True 26 | end 27 | if (line[0] = "n) | line[0] = "N) then 28 | return False 29 | end 30 | 31 | // Quit. 32 | break on (line[0] = "q) | (line[0] = "Q) 33 | end 34 | return Null 35 | end 36 | 37 | end 38 | 39 | class Question (Node) 40 | var question := '' 41 | var ifYes := Null 42 | var ifNo := Null 43 | 44 | init (question, ifYes, ifNo) 45 | self.question := question 46 | self.ifYes := ifYes 47 | self.ifNo := ifNo 48 | end 49 | 50 | func ask() 51 | // Recurse into the branches. 52 | if self.promptYesNo(self.question) then 53 | var result := self.ifYes.ask() 54 | if result <> Null then self.ifYes := result end 55 | else 56 | var result := self.ifNo.ask() 57 | if result <> Null then self.ifNo := result end 58 | end 59 | end 60 | end 61 | 62 | class Animal (Node) 63 | var name := '' 64 | init (name) 65 | self.name = name 66 | end 67 | 68 | func ask() 69 | // Hit a leaf, so see if we guessed it. 70 | if self.promptYesNo('Is it a ' + self.name + '?') then 71 | print('I won! Let us play again!') 72 | return Null 73 | end 74 | 75 | // Nope, so add a new animal and turn this node into a branch. 76 | var name := self.promptString('I lost! What was your animal?') 77 | var question := self.promptString('What question would distinguish a ' + 78 | self.name + ' from a ' + name + '?') 79 | var isYes := self.promptYesNo( 80 | 'Is the answer to the question "yes" for a ' + name + '?') 81 | print('I will remember that. Let us play again!') 82 | 83 | var animal := Animal(name) 84 | return Question(question, 85 | if isYes then animal else self, 86 | if isYes then self else animal) 87 | end 88 | end 89 | 90 | 91 | var root := Question('Does it live in the water?', 92 | Animal('frog'), Animal('goat')) 93 | 94 | // Play games until the user quits. 95 | 96 | while True do 97 | root.ask() 98 | end 99 | 100 | -------------------------------------------------------------------------------- /interpreter/examples/anon.gear: -------------------------------------------------------------------------------- 1 | // anonymous function 2 | 3 | func calc(x, y, function) 4 | return function(x,y) 5 | end 6 | 7 | var sum := calc(20, 22, (a,b) => a+b) 8 | var product := calc(2, 21, (a,b) => a*b) 9 | 10 | print('Sum is: \(sum) and product is: \(product).') 11 | 12 | -------------------------------------------------------------------------------- /interpreter/examples/anonym.gear: -------------------------------------------------------------------------------- 1 | 2 | func calc(times n, function) 3 | for var k:=1 where k<=n, k+=1 do 4 | print(function(k), terminator: ' ') 5 | end 6 | print() 7 | end 8 | 9 | calc(times: 5, x=>x^2) // 1 4 9 16 25 10 | calc(times: 5, x=>x^3) // 1 8 27 64 125 11 | calc(times: 5, x=>x^4) // 1 16 81 256 625 12 | 13 | 14 | /* 15 | 16 | In FPC would be: 17 | 18 | program Name; 19 | 20 | type 21 | TLambda = function(x: Integer): Integer; 22 | 23 | function Calc(n: Integer; Lambda: TLambda): Integer; 24 | var 25 | k: Integer; 26 | begin 27 | for k := 1 to n do 28 | begin 29 | Write(Lambda(k), ' '); 30 | end; 31 | WriteLn; 32 | end; 33 | 34 | function x2(x: Integer): Integer; 35 | begin 36 | Result := x*x; 37 | end; 38 | 39 | function x3(x: Integer): Integer; 40 | begin 41 | Result := x*x*x; 42 | end; 43 | 44 | function x4(x: Integer): Integer; 45 | begin 46 | Result := x*x*x*x; 47 | end; 48 | 49 | begin 50 | Calc(5, @x2); 51 | Calc(5, @x3); 52 | Calc(5, @x4); 53 | end. 54 | 55 | */ 56 | -------------------------------------------------------------------------------- /interpreter/examples/area.gear: -------------------------------------------------------------------------------- 1 | let Pi := 3.1415926 2 | var radius := 2 3 | val area 4 | return Pi * radius^2 5 | end 6 | 7 | print(area) // prints 12.5663704 8 | radius := 1 9 | print(area) // prints 3.1415926 10 | 11 | 12 | -------------------------------------------------------------------------------- /interpreter/examples/array.gear: -------------------------------------------------------------------------------- 1 | use system 2 | 3 | var numbers := [1,2,3,4,5,6,7,8,9,10] 4 | 5 | numbers.forEach( 6 | func(x) 7 | let squared := x^2 8 | print('Number \(x) squared is: \(squared).') 9 | end) 10 | 11 | let squaredNumbers := numbers.map(x=>x^2) 12 | print(squaredNumbers) 13 | 14 | let evenNumbers := numbers.filter(x=>x%2=0) 15 | print(evenNumbers) 16 | 17 | let sum := numbers.reduce(0, (x,y)=>x+y) 18 | print(sum) 19 | 20 | let factorial := numbers.reduce(1, (x,y)=>x*y) 21 | print(factorial) 22 | 23 | let animals := ['lion', 'monkey', 'elephant'] 24 | print(animals) 25 | 26 | -------------------------------------------------------------------------------- /interpreter/examples/ascii.gear: -------------------------------------------------------------------------------- 1 | // ascii 2 | 3 | use system 4 | let chars := Array('0123456789abcdefghijklmnopqrstuvwxyz') 5 | 6 | for each char in chars do 7 | print('Char \(char) has ascii code \(ord(char)).') 8 | end 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /interpreter/examples/booltest.gear: -------------------------------------------------------------------------------- 1 | 2 | print( 1 | 3 ) // 01 or 11 = 11 3 | print( 1 & 3 ) // 01 and 11 = 01 4 | print( 1 ~ 3 ) // 01 xor 11 = 10 5 | print( !3 ) // not 11 = -100 6 | print( !4 ) // not 100 = -0101 7 | print( !-4 ) // not -100 = 011 8 | print( !-5 ) // not -101 = 100 9 | 10 | print( !7 ) // not 111 = -1000 11 | 12 | print((7>6) | False) 13 | 14 | //True /\ False 15 | //True \/ False 16 | 17 | print(!True) 18 | 19 | -------------------------------------------------------------------------------- /interpreter/examples/chars.gear: -------------------------------------------------------------------------------- 1 | // array of char 2 | 3 | use system 4 | 5 | let a := 'Hello world, my answer is 42' 6 | let chars := Array(a) 7 | 8 | print(chars) 9 | 10 | 11 | for each char in Array('Hello world, my answer is 42') do 12 | print(char) 13 | end 14 | 15 | -------------------------------------------------------------------------------- /interpreter/examples/class.gear: -------------------------------------------------------------------------------- 1 | class Test 2 | var a := 0 3 | init(a) 4 | self.a := a 5 | end 6 | end 7 | 8 | -------------------------------------------------------------------------------- /interpreter/examples/class1.gear: -------------------------------------------------------------------------------- 1 | // harry and sally 2 | 3 | class Date 4 | var day := 1, month := 'January', year := 1980 5 | init(.day, .month, .year) 6 | self.day := day 7 | self.month := month 8 | self.year := year 9 | end 10 | func toString() 11 | return 'Date: \(self.day)-\(self.month)-\(self.year)' 12 | end 13 | end 14 | 15 | class Person 16 | var name := 'Person' 17 | var birthDate := Date() 18 | init(name, .birthDate) 19 | self.name := name 20 | self.birthDate := birthDate 21 | end 22 | func toString() 23 | return self.name + ': ' + self.birthDate.toString() 24 | end 25 | end 26 | 27 | var Harry := Person('Harry', birthDate: Date(day: 23, month: 'February', year: 1987)) 28 | var Sally := Person('Sally', birthDate: Date(day: 18, month: 'July', year: 1992)) 29 | 30 | print(Harry.toString()) 31 | print(Sally.toString()) 32 | print(Person().toString()) 33 | 34 | -------------------------------------------------------------------------------- /interpreter/examples/class2.gear: -------------------------------------------------------------------------------- 1 | // inheritance 2 | 3 | class Parent 4 | func method() 5 | print('Parent Method') 6 | end 7 | end 8 | 9 | class Child(Parent) 10 | func method() 11 | inherited method() 12 | print('Child Method') 13 | end 14 | end 15 | 16 | var child := Child() 17 | child.method() 18 | 19 | -------------------------------------------------------------------------------- /interpreter/examples/class3.gear: -------------------------------------------------------------------------------- 1 | // iniherited init 2 | 3 | class Circle 4 | var radius := 1 5 | val area := pi() * self.radius^2 6 | init(.radius) 7 | self.radius := radius 8 | end 9 | end 10 | 11 | class Cylinder (Circle) 12 | var height := 0 13 | val volume := self.area * self.height 14 | init(.radius, .height) 15 | inherited(radius: radius) 16 | self.height := height 17 | end 18 | end 19 | 20 | class Sphere (Circle) 21 | init(.radius) 22 | inherited(radius: radius) 23 | end 24 | val volume := (4/3)*pi()*self.radius^3 25 | end 26 | 27 | var circle := Circle(radius: 1) 28 | var cylinder := Cylinder(radius: 2, height: 10) 29 | var sphere1 := Sphere(radius:2) 30 | var sphere2 := Sphere(radius:3) 31 | 32 | print(circle.radius) // prints 1 33 | print(circle.area) // prints 3.14159265358979 34 | print(cylinder.radius) // prints 2 35 | print(cylinder.area) // prints 12.5663706143592 36 | print(cylinder.volume) // prints 125.663706143592 37 | 38 | print(sphere1.volume) 39 | print(sphere1.radius) 40 | print(sphere2.volume) 41 | print(sphere2.radius) 42 | 43 | -------------------------------------------------------------------------------- /interpreter/examples/classclass.gear: -------------------------------------------------------------------------------- 1 | 2 | // test class inside class 3 | 4 | class Date 5 | var day := 1, month := 1, year := 1 6 | init(day, month, year) 7 | self.day := day 8 | self.month := month 9 | self.year := year 10 | end 11 | func toString() => '\(self.day)-\(self.month)-\(self.year)' 12 | end 13 | 14 | class Person 15 | 16 | var birthDate := Date() 17 | var name := '' 18 | init(name, birthDate) 19 | self.name := name 20 | self.birthDate := birthDate 21 | end 22 | func toString() => '\(self.name), born: \(self.birthDate.toString())' 23 | end 24 | 25 | var person := Person() 26 | var Jeroen := Person('Jeroen', Date(18, 01, 1964)) 27 | print(Jeroen.toString()) 28 | 29 | -------------------------------------------------------------------------------- /interpreter/examples/count.gear: -------------------------------------------------------------------------------- 1 | 2 | let m := milliseconds() 3 | for var i:=0 where i<10000000, i+=1 do 4 | end 5 | 6 | print(milliseconds()-m) 7 | 8 | -------------------------------------------------------------------------------- /interpreter/examples/curry.gear: -------------------------------------------------------------------------------- 1 | // currying 2 | 3 | var square := x => x^2 4 | print(square(16)) 5 | 6 | var helloWorld := func() 7 | print('Hello world!') 8 | end 9 | 10 | helloWorld() // Hello World! 11 | 12 | var z := (x=>2^x)(9) // parentheses are required here! 13 | print(z) // 512 14 | 15 | print((x=>2^x)(9)) 16 | 17 | -------------------------------------------------------------------------------- /interpreter/examples/dict.gear: -------------------------------------------------------------------------------- 1 | use system 2 | 3 | var dict := [ 4 | 0: 'Zero', 5 | 1: 'One', 6 | 2: 'Two', 7 | 3: 'Three', 8 | 4: 'Four', 9 | 5: 'Five', 10 | 6: 'Six', 11 | 7: 'Seven', 12 | 8: 'Eight', 13 | 9: 'Nine', 14 | 10: 'Ten'] 15 | 16 | for each item in dict do 17 | print(item.key, ': ', item.value) 18 | end 19 | 20 | dict.set(sorted: True) 21 | print(dict) 22 | 23 | 24 | -------------------------------------------------------------------------------- /interpreter/examples/dict2.gear: -------------------------------------------------------------------------------- 1 | use system 2 | 3 | let table := [ 4 | '+': (x,y)=>x+y, 5 | '-': (x,y)=>x-y, 6 | '*': (x,y)=>x*y, 7 | '/': (x,y)=>x/y, 8 | '%': (x,y)=>x%y] 9 | 10 | var result := table['*'](7,9) 11 | print(result) 12 | 13 | func calc(x,y) 14 | for each item in table do 15 | print(x, item.key, y, '\t=\t', item.value(x,y)) 16 | end 17 | end 18 | 19 | calc(16,12) 20 | 21 | -------------------------------------------------------------------------------- /interpreter/examples/dictio.gear: -------------------------------------------------------------------------------- 1 | 2 | use system 3 | 4 | let milesToPoint := ['point1':120.0,'point2':50.0,'point3':70.0] 5 | let kmToPoint := milesToPoint.values.map(miles => miles * 1.6093 ) 6 | print(kmToPoint) 7 | 8 | -------------------------------------------------------------------------------- /interpreter/examples/double.gear: -------------------------------------------------------------------------------- 1 | // test double precision 2 | print(9999999999999999= 3 | 10000000000000000) 4 | let x := 0.1 + 0.2 5 | let y := 0.3 6 | print(x = y) 7 | 8 | var a := 'a' 9 | var b := 2 10 | var c := a + b 11 | print(c) 12 | var d := True | False 13 | print(d) 14 | print([] + []) 15 | 16 | -------------------------------------------------------------------------------- /interpreter/examples/elif.gear: -------------------------------------------------------------------------------- 1 | let number := 100 2 | var guess := 1000 3 | 4 | if guess < number then 5 | print('Too low.') 6 | elseif guess = number then 7 | print('You win!') 8 | else 9 | print('Too high.') 10 | end 11 | 12 | -------------------------------------------------------------------------------- /interpreter/examples/elseif.gear: -------------------------------------------------------------------------------- 1 | // test elseif 2 | let max := 100 3 | var number := randomLimit(max) + 1 4 | 5 | while True do 6 | print('Guess a number (1 to ', max, '): ', terminator: '') 7 | 8 | ensure var guess := toNum(readln()) where guess <> Null 9 | else 10 | print('That`s not a number!') 11 | continue 12 | end 13 | 14 | ensure (guess > 0) & (guess <= max) 15 | else 16 | print('That number is not in range 1 to ', max) 17 | continue 18 | end 19 | 20 | if guess < number then 21 | print('Too low.') 22 | elseif guess = number then 23 | print('You win!') 24 | break 25 | else 26 | print('Too high.') 27 | end 28 | 29 | end 30 | 31 | -------------------------------------------------------------------------------- /interpreter/examples/elseif2.gear: -------------------------------------------------------------------------------- 1 | let number := 100 2 | var guess := 1000 3 | 4 | if guess < number then 5 | print('Too low.') 6 | elseif guess = number then 7 | print('You win!') 8 | elseif (guess > number) & (guess <= 1000) then 9 | print('Too high.') 10 | elseif (guess > 1000) & (guess < 10000) then 11 | print('Way too high.') 12 | else 13 | print('Out of reach') 14 | end 15 | 16 | -------------------------------------------------------------------------------- /interpreter/examples/enum.gear: -------------------------------------------------------------------------------- 1 | /*enum Color 2 | (None 3 | case Primary: Red, Yellow, Blue 4 | case Secondary: Orange, Green, Brown) 5 | end 6 | 7 | func randomColor() => 8 | match randomLimit(7)+1 9 | if 1 then Color.Red 10 | if 2 then Color.Yellow 11 | if 3 then Color.Blue 12 | if 4 then Color.Orange 13 | if 5 then Color.Green 14 | if 6 then Color.Brown 15 | else Color.None 16 | 17 | var myColor := randomColor() 18 | 19 | if myColor in Color.Primary then 20 | print(myColor, ' is a primary color.') 21 | elseif myColor in Color.Secondary then 22 | print(myColor, ' is a secondary color.') 23 | else 24 | print(myColor) 25 | end 26 | */ 27 | 28 | use system 29 | 30 | enum Color 31 | (None 32 | case Primary: Red, Yellow, Blue 33 | case Secondary: Orange, Green, Brown) 34 | end 35 | 36 | for each color in Color.Elements where color in Color.Primary do 37 | print(color) 38 | end 39 | 40 | print(Color.Elements) 41 | 42 | -------------------------------------------------------------------------------- /interpreter/examples/expr.gear: -------------------------------------------------------------------------------- 1 | 2 | print(8/2*(2+2)) 3 | print(8/(2*(2+2))) 4 | 5 | -------------------------------------------------------------------------------- /interpreter/examples/fib.gear: -------------------------------------------------------------------------------- 1 | func fib(n) => if n>2 then fib(n-1) + fib(n-2) else 1 2 | 3 | let n := 20 4 | 5 | print('fib(\(n)) = \(fib(n)).') 6 | 7 | -------------------------------------------------------------------------------- /interpreter/examples/fibonacci.gear: -------------------------------------------------------------------------------- 1 | func Fibonacci(n) 2 | if n = 0 then 3 | return 0 4 | elseif n = 1 then 5 | return 1 6 | else 7 | return Fibonacci(n-1) + Fibonacci(n-2) 8 | end 9 | end 10 | 11 | let m := milliseconds() 12 | 13 | print(Fibonacci(30)) 14 | 15 | print(milliseconds() - m) 16 | 17 | 18 | func Fib(n) => 19 | match n 20 | if 0,1 then n 21 | else Fib(n-1) + Fib(n-2) 22 | 23 | let o := milliseconds() 24 | 25 | print(Fib(30)) 26 | 27 | print(milliseconds() - o) 28 | 29 | -------------------------------------------------------------------------------- /interpreter/examples/file.gear: -------------------------------------------------------------------------------- 1 | 2 | func process(.fileName) 3 | let inputFile := fileOpen(fileName, forReading) 4 | 5 | if inputFile = -1 then 6 | print('Error opening file "\(fileName)".') 7 | return Null 8 | end 9 | 10 | let fileSize := fileSeek(inputFile, 0, fromEnd) 11 | 12 | fileSeek(inputFile, 0, fromBeginning) 13 | 14 | let bytesRead := fileRead(inputFile) 15 | if length(bytesRead) < fileSize then 16 | print('Error reading file "\(fileName)".') 17 | return Null 18 | end 19 | 20 | fileClose(inputFile) 21 | 22 | return (bytesRead, fileSize) 23 | end 24 | 25 | print('Enter file name: ') 26 | let file := readln() 27 | let contents := process(fileName: file) 28 | print(contents.1) 29 | 30 | let size := contents.2 31 | print('size: \(size)') 32 | -------------------------------------------------------------------------------- /interpreter/examples/files.gear: -------------------------------------------------------------------------------- 1 | // test file functions 2 | 3 | use system 4 | 5 | let f := fileOpen('/Users/for.txt', forReading) 6 | print(f) 7 | 8 | let result := fileRead(f) // is an array of byte 9 | 10 | fileClose(f) 11 | 12 | //print(result) 13 | 14 | extension Array 15 | func toStr() 16 | var result := '' 17 | for var i := 0 where i 6.0 then 11 | print('You passed!') 12 | elseif (average>5.0) & (average<=6.0) then 13 | print('You need to work harder!') 14 | else 15 | print('You failed!') 16 | end 17 | 18 | //print(average) // Prints 7.6 19 | 20 | 21 | /* 22 | let scores := ['Math': 8.3, 'Science': 7.7, 'English': 9.0, 'Economy': 5.4] 23 | var sum := 0 24 | for each score in scores do 25 | sum += score.value 26 | print('You''re \(score.key) result was \(score.value).') 27 | end 28 | let average := sum / scores.count 29 | print('The average is \(average).') 30 | */ 31 | 32 | -------------------------------------------------------------------------------- /interpreter/examples/foreach.gear: -------------------------------------------------------------------------------- 1 | 2 | use system 3 | 4 | let list := [1,2,3,4,5,6,7,8,9] 5 | 6 | /* 7 | while var i:=0 where i < list.count do 8 | print(list[i]) 9 | i+=1 10 | end 11 | */ 12 | 13 | for each item in list where item%2=0 do 14 | print(item, terminator: ' | ') 15 | end 16 | print() 17 | 18 | 19 | -------------------------------------------------------------------------------- /interpreter/examples/func.gear: -------------------------------------------------------------------------------- 1 | func hello(.person, .day) 2 | print('Hello \(person), it''s \(day) today.') 3 | end 4 | 5 | hello(person: 'Jerry', day: today()) 6 | 7 | -------------------------------------------------------------------------------- /interpreter/examples/funcasparam.gear: -------------------------------------------------------------------------------- 1 | // func as parameter 2 | 3 | func add2Numbers(a,b) => a+b 4 | func mul2Numbers(a,b) => a*b 5 | 6 | func calc(x, y, function) 7 | return function(x,y) 8 | end 9 | 10 | var sum := calc(20, 22, add2Numbers) 11 | var product := calc(2, 21, mul2Numbers) 12 | 13 | print('Sum is: \(sum) and product is: \(product).') 14 | 15 | -------------------------------------------------------------------------------- /interpreter/examples/funcclass.gear: -------------------------------------------------------------------------------- 1 | use system 2 | 3 | func calculate(.scores) 4 | class Statistics 5 | var min := 0, max := 0, sum := 0, avg := 0 6 | end 7 | var statistics := Statistics() 8 | 9 | for each score in scores do 10 | if score > statistics.max then 11 | statistics.max := score 12 | elseif score < statistics.max then 13 | statistics.min := score 14 | end 15 | statistics.sum += score 16 | end 17 | statistics.avg := statistics.sum / scores.count 18 | 19 | return statistics 20 | end 21 | 22 | let statistics := calculate(scores: [6, 7, 8, 9, 5, 4, 10, 3]) 23 | print(statistics.min) 24 | print(statistics.max) 25 | print(statistics.sum) 26 | print(statistics.avg) 27 | 28 | -------------------------------------------------------------------------------- /interpreter/examples/hanoi.gear: -------------------------------------------------------------------------------- 1 | //hanoi 2 | 3 | func tower(diskNumbers, source, auxilary, destination) 4 | if diskNumbers = 1 then 5 | print('\(source) \t-> \(destination)') 6 | else 7 | tower(diskNumbers-1, source, destination, auxilary) 8 | print('\(source) \t-> \(destination)') 9 | tower(diskNumbers-1, auxilary, source, destination) 10 | end 11 | end 12 | 13 | tower(3, 'src', 'aux', 'dest') 14 | 15 | -------------------------------------------------------------------------------- /interpreter/examples/hello.gear: -------------------------------------------------------------------------------- 1 | 2 | var s := () => 'Hello world!' 3 | print(s()) 4 | 5 | val t := 'Hello world!' 6 | print(t) 7 | 8 | -------------------------------------------------------------------------------- /interpreter/examples/helloWorld.gear: -------------------------------------------------------------------------------- 1 | 2 | print('Hello world!') 3 | 4 | // or 5 | 6 | var helloWorld := func() print('Hello world!') end 7 | helloWorld() 8 | 9 | // or 10 | 11 | func helloworld() 12 | print('Hello world!') 13 | end 14 | 15 | helloworld() 16 | 17 | func greetings(to name) 18 | print('Hello \(name)!') 19 | end 20 | 21 | greetings(to: 'world') 22 | 23 | -------------------------------------------------------------------------------- /interpreter/examples/ifthen.gear: -------------------------------------------------------------------------------- 1 | 2 | func pow(x, n, lim) 3 | if let v := x^n where v < lim then 4 | return v 5 | else 6 | print('\(v) >= \(lim)') 7 | end 8 | return lim // 'v' can't be used here 9 | end 10 | 11 | print(pow(3,2,10)) 12 | print(pow(3,3,20)) 13 | 14 | -------------------------------------------------------------------------------- /interpreter/examples/ifvar.gear: -------------------------------------------------------------------------------- 1 | 2 | print('gimme a number: ') 3 | if var x := toNum(readln()) where x <> Null then 4 | x := x^2 5 | print(x) 6 | else 7 | print('That''s not a number') 8 | end 9 | 10 | -------------------------------------------------------------------------------- /interpreter/examples/initclosure.gear: -------------------------------------------------------------------------------- 1 | // test closure in init() 2 | 3 | use system 4 | 5 | class Function 6 | var function := Null 7 | init(function) 8 | self.function := function 9 | end 10 | end 11 | 12 | let fx := Function(x=>x^2+4*x+4) 13 | 14 | print(fx.function(2)) 15 | 16 | -------------------------------------------------------------------------------- /interpreter/examples/integral.gear: -------------------------------------------------------------------------------- 1 | func integral(f, from a, to b, steps n) 2 | var sum := 0 3 | let dt := (b-a)/n 4 | for var i := 0 where ix^2-2*x+4, from: 0, to: 1, steps: 10000)) 12 | 13 | // Calculate the integral over function f(x) = x^3 in 10000 steps 14 | print(integral(x=>x^3, from: 0, to: 1, steps: 10000)) 15 | 16 | // Calculate the integral over function 3) f(x) = x^2 + 4*x - 21 in 10000 steps 17 | print(integral(x=>x^2 + 4*x - 21, from: 0, to: 1, steps: 10000)) 18 | 19 | // integral of half circle 20 | // x^2 + y^2 = 1 21 | // y^2 = 1 - x^2 22 | // y = sqrt(1-x^2) 23 | print(integral(x=>sqrt(1-x^2), from: -1, to: 1, steps: 10000)) // pi/2 24 | 25 | 26 | print(pi()) 27 | 28 | -------------------------------------------------------------------------------- /interpreter/examples/interpol.gear: -------------------------------------------------------------------------------- 1 | // interpolated strings 2 | 3 | let x := 6 4 | let y := 7 5 | 6 | var s := 'I''ve got \(x+y) things to do.' 7 | 8 | print(s) 9 | 10 | 11 | print('The number is \(6*7)!. And \(x*y) as well.') 12 | 13 | 14 | print('this is a backslash \. + a line ending\n\t duh') 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /interpreter/examples/interpol2.gear: -------------------------------------------------------------------------------- 1 | let apples := 4 2 | let bananas := 5 3 | print('I have \(apples) apples and \(bananas) bananas, so \(apples+bananas) pieces of fruit.') 4 | 5 | let truth := True 6 | print('Is the truth \(truth | False)?') 7 | 8 | print('Hello ' + 'world' + "!) 9 | 10 | let c := '🤪' 11 | print('That''s a nice smiley: \(c)') 12 | print('Number (' + 42 + ')') 13 | 14 | func add(a,b) => a+b 15 | print('I have \(add(apples,bananas)) pieces of fruit.') 16 | 17 | 18 | -------------------------------------------------------------------------------- /interpreter/examples/is.gear: -------------------------------------------------------------------------------- 1 | class Root 2 | var name := 'Root' 3 | end 4 | 5 | class First (Root) 6 | end 7 | 8 | class Second (Root) 9 | end 10 | 11 | class Third (Second) 12 | end 13 | class Fourth 14 | end 15 | 16 | var sec := Second() 17 | 18 | print('Start: ', sec.name) 19 | 20 | if sec is Root then 21 | print('Root') 22 | elseif sec is First then 23 | print('First') 24 | elseif sec is Second then 25 | print('Second') 26 | elseif sec is Third then 27 | print('Third') 28 | else 29 | print('None of the above') 30 | end 31 | 32 | -------------------------------------------------------------------------------- /interpreter/examples/iter.gear: -------------------------------------------------------------------------------- 1 | use system 2 | let interestingNumbers := [ 3 | 'Prime': [2, 3, 5, 7, 11, 13], 4 | 'Fibonacci': [1, 1, 2, 3, 5, 8], 5 | 'Square': [1, 4, 9, 16, 25] 6 | ] 7 | var largest := 0 8 | for each type in interestingNumbers do 9 | for each number in type.value do //dict iterator has key, value pairs 10 | if number > largest then 11 | largest := number 12 | end 13 | end 14 | end 15 | print(largest) 16 | // Prints "25" 17 | -------------------------------------------------------------------------------- /interpreter/examples/linsearch.gear: -------------------------------------------------------------------------------- 1 | /* 2 | after an example of Coffeescript: 3 | 4 | names = ["Ivan", "Joanna", "Nikolay", "Mihaela"] 5 | linearSearch = (searchName) -> alert(name) for name in names when name is searchName 6 | 7 | */ 8 | 9 | 10 | use system 11 | 12 | let names := ['Ivan', 'Joanna', 'Nikolay', 'Mihaela'] 13 | 14 | let linearSearch := 15 | func (searchName) => { name for name in names where name = searchName } 16 | 17 | print(linearSearch('Nikolay')) 18 | 19 | -------------------------------------------------------------------------------- /interpreter/examples/listbuild.gear: -------------------------------------------------------------------------------- 1 | // list builder 2 | use system 3 | 4 | //var result := Range(1,100).filter(x=>x^2>3).map(x=>2*x) 5 | var result := (1..100).filter(x=>x^2>3).map(x=>2*x) 6 | print(result) 7 | 8 | // as opposed to 9 | 10 | var other := {2*x for x in 1..100 where x^2>3} 11 | print(other) 12 | 13 | -------------------------------------------------------------------------------- /interpreter/examples/mandelbrot.gear: -------------------------------------------------------------------------------- 1 | use system 2 | 3 | var yMin := -0.2 4 | var yMax := 0.1 5 | var xMin := -1.5 6 | var xMax := -1.1 7 | 8 | for each yPixel in 0..32 do 9 | var y := (yPixel / 24) * (yMax - yMin) + yMin 10 | for each xPixel in 0..80 do 11 | var x := (xPixel / 79) * (xMax - xMin) + xMin 12 | var pixel := '' 13 | var x0 := x 14 | var y0 := y 15 | for each iter in 0..80 do 16 | var x1 := (x0 * x0) - (y0 * y0) 17 | var y1 := 2 * x0 * y0 18 | 19 | // Add the seed. 20 | x1 += x 21 | y1 += y 22 | 23 | x0 := x1 24 | y0 := y1 25 | 26 | // Stop if the point escaped. 27 | var d := (x0 * x0) + (y0 * y0) 28 | if (d > 4) then 29 | pixel := ' .:;+=xX$&'[floor(iter / 8)] 30 | break 31 | end 32 | end 33 | 34 | print(pixel, terminator: '') 35 | end 36 | 37 | print() 38 | end 39 | 40 | -------------------------------------------------------------------------------- /interpreter/examples/match.gear: -------------------------------------------------------------------------------- 1 | let bar := 2 2 | 3 | let x := 4 | match bar 5 | if 1 then func() print('func 1') end 6 | if 2 then func() print('func 2') end 7 | else func() print('default func') end 8 | 9 | x() 10 | 11 | -------------------------------------------------------------------------------- /interpreter/examples/matrix.gear: -------------------------------------------------------------------------------- 1 | // matrices 2 | 3 | var m := [1,2,3,4,5,6,7,8,9] 4 | var n := [3,2,1,6,5,4,9,8,7] 5 | 6 | print(m::n) 7 | 8 | 9 | -------------------------------------------------------------------------------- /interpreter/examples/missing.gear: -------------------------------------------------------------------------------- 1 | // missing number in array 2 | 3 | use system 4 | 5 | func missing(numbers) 6 | let count := numbers.count 7 | var sum := 0 8 | for each i in 0.. m then 20 | count := m 21 | else 22 | i := m+1 23 | end 24 | end 25 | return count 26 | end 27 | 28 | let a := [0,1,2,4,5,6] 29 | 30 | print(missing(a)) 31 | print(missing2(a)) 32 | 33 | -------------------------------------------------------------------------------- /interpreter/examples/multiline.gear: -------------------------------------------------------------------------------- 1 | // multiline 2 | 3 | let StephenHawkingQuote := 4 | 'When we understand string theory, we will know how the universe began. 5 | \tIt won''t have much effect on how we live, but it is important to understand 6 | \tthere we come from and what we can expect to find as we explore.' 7 | 8 | print(StephenHawkingQuote) 9 | 10 | let apples := 6 11 | 12 | print('No of apples: \(apples.') 13 | 14 | 15 | let EdwardWittenQuote := 16 | 'Technically you need the extra dimensions. At first people didn''t like them too 17 | much, but they''ve got a big benefit, which is that the ability of string theory 18 | to describe all the elementary particles and their forces along with gravity 19 | depends on using the extra dimensions.' 20 | 21 | let quotes := 'Edward said: \(EdwardWittenQuote) 22 | \tthen followed by Stephen''s quote: 23 | \(StephenHawkingQuote)' 24 | 25 | print(quotes) 26 | 27 | -------------------------------------------------------------------------------- /interpreter/examples/mutability.gear: -------------------------------------------------------------------------------- 1 | // test immutability of fields 2 | 3 | class Point 4 | let x:=0, y:=0 5 | init(.x, .y) 6 | self.x:=x 7 | self.y:=y 8 | end 9 | func distance(to point) 10 | return sqrt((point.x-self.x)^2 + (point.y-self.y)^2) 11 | end 12 | end 13 | 14 | var p0 := Point(), p1 := Point(x:1,y:1), p2 := Point(x:3,y:4) 15 | 16 | print(p1.distance(to: p0)) 17 | print(p2.distance(to: p0)) 18 | 19 | //p0.x := 1 // error x is immutable 20 | 21 | extension Point 22 | func setXValue(to newValue) 23 | self.x := Null 24 | self.x := newValue 25 | end 26 | 27 | func setYValue(to newValue) 28 | self.y := Null 29 | self.y := newValue 30 | end 31 | end 32 | 33 | p0.setXValue(to:1) // error x is immutable 34 | p0.setYValue(to:1) // error y is immutable 35 | 36 | 37 | -------------------------------------------------------------------------------- /interpreter/examples/nested.gear: -------------------------------------------------------------------------------- 1 | //nested 2 | 3 | func greet(name) 4 | 5 | var result := name 6 | func makeGreeting() 7 | result := 'Hello ' + name 8 | end 9 | 10 | makeGreeting() 11 | 12 | return result 13 | end 14 | 15 | print(greet('Emanuelle')) 16 | 17 | -------------------------------------------------------------------------------- /interpreter/examples/num2str.gear: -------------------------------------------------------------------------------- 1 | // test string to number and number to string 2 | 3 | var a := '3.1415' 4 | print(toNum(a)) 5 | 6 | var b := 3.1415 7 | print(toStr(b)) 8 | 9 | print(toNum(a) = b) 10 | 11 | print('a' = 'a') 12 | print(a = toStr(b)) 13 | 14 | print(toStr(False)) 15 | print(toStr(pi())) 16 | print(toStr(b=pi())) 17 | print(toStr(111)) 18 | print(toStr("a)) 19 | 20 | print(toNum(True)) 21 | 22 | -------------------------------------------------------------------------------- /interpreter/examples/overload.gear: -------------------------------------------------------------------------------- 1 | 2 | // overloading functions 3 | 4 | func add(a, to b) => a+b 5 | 6 | print(add(2, to: 3)) 7 | 8 | func add(c, plus d) => c+d 9 | 10 | print(add(4, plus: 5)) 11 | 12 | func add(e,f) => e+f 13 | print(add(6, 5)) 14 | 15 | print(add) 16 | 17 | 18 | class Class 19 | var field := Null 20 | init(.field) 21 | self.field := field 22 | end 23 | func toString() => self.field 24 | func toString(name) 25 | return (self.field, name) 26 | end 27 | end 28 | 29 | print(Class) 30 | 31 | var c := Class() 32 | 33 | print(c.field) 34 | 35 | var d := Class(field: 'test1') 36 | print(d.field) 37 | print(d.toString()) 38 | 39 | 40 | -------------------------------------------------------------------------------- /interpreter/examples/people.gear: -------------------------------------------------------------------------------- 1 | use person 2 | use arrays 3 | 4 | var people := [ 5 | Person(name: 'Jerry', address: 'Milano, Italy', age: 39, income: 73000, 6 | cars: ['Opel Astra', 'Citroen C1']), 7 | Person(name: 'Cathy', address: 'Berlin, Germany', age: 34, income: 75000, 8 | cars: ['Audi A3']), 9 | Person(name: 'Bill', address: 'Brussels, Belgium', age: 48, income: 89000, 10 | cars: ['Volco XC60', 'Mercedes B', 'Smart 4x4']), 11 | Person(name: 'Francois', address: 'Lille, France', age: 56, income: 112000, 12 | cars: ['Volco XC90', 'Jaguar X-type']), 13 | Person(name: 'Joshua', address: 'Madrid, Spain', age: 43, income: 42000, 14 | cars: []) 15 | ] 16 | 17 | let names := people.map(person=>person.name) 18 | let totalIncome := people.map(person=>person.income).reduce(0, (x,y)=>x+y) 19 | let allCars := people.flatMap(person=>person.cars) 20 | 21 | print(names) 22 | print(totalIncome) 23 | print(allCars) 24 | 25 | -------------------------------------------------------------------------------- /interpreter/examples/person.gear: -------------------------------------------------------------------------------- 1 | class Person 2 | var name := '' 3 | var address := '' 4 | var age := 0 5 | var income := 0 6 | var cars := [] 7 | 8 | init(.name, .address, .age, .income, .cars) 9 | self.name := name 10 | self.address := address 11 | self.age := age 12 | self.income := income 13 | self.cars := cars 14 | end 15 | end 16 | 17 | -------------------------------------------------------------------------------- /interpreter/examples/point.gear: -------------------------------------------------------------------------------- 1 | // based on Dart's example 2 | // https://en.wikipedia.org/wiki/Dart_(programming_language) 3 | 4 | class Point 5 | var x := 0, y := 0 6 | init(x, y) 7 | self.x := x 8 | self.y := y 9 | end 10 | 11 | val origin := Point() 12 | 13 | func distanceTo(other) 14 | let dx := self.x - other.x 15 | let dy := self.y - other.y 16 | return sqrt(dx*dx + dy*dy) 17 | end 18 | end 19 | 20 | var p1 := Point(10,10) 21 | var p2 := Point().origin 22 | var distance := p1.distanceTo(p2) 23 | print(distance) 24 | 25 | -------------------------------------------------------------------------------- /interpreter/examples/primes.gear: -------------------------------------------------------------------------------- 1 | 2 | use system 3 | //[n in [2..N] | forall m in {2..n - 1} | n mod m > 0] 4 | 5 | //var primes := N => (2..N).forEach(n=>(2..0)) 6 | 7 | 8 | 9 | func isPrime(num) 10 | if num < 2 then 11 | return False 12 | end 13 | 14 | for var i := 2 where i < num, i+=1 do 15 | if num%i=0 then 16 | return False 17 | end 18 | end 19 | return True 20 | end 21 | 22 | var primes := (2..100).filter(n=>isPrime(n)) 23 | print(primes) 24 | 25 | 26 | /* 27 | var primes := (3..100).forEach( 28 | 29 | var primes := [] 30 | for var n:=3 where n<=100, n+=2 do 31 | if primes.forEach(prime=>n%prime>0) then 32 | primes.add(value: n) 33 | end 34 | end 35 | 36 | print(primes) 37 | */ 38 | 39 | -------------------------------------------------------------------------------- /interpreter/examples/primes2.gear: -------------------------------------------------------------------------------- 1 | 2 | use system 3 | 4 | 5 | /*func isPrime(number) 6 | let sqrtNum := sqrt(number) 7 | for var i:=3 where i<= sqrtNum, i+=2 do 8 | if number % i = 0 then 9 | return False 10 | end 11 | end 12 | return True 13 | end 14 | */ 15 | //var primes := (3..<10000).step(by:2).filter(n=>isPrime(n)) 16 | 17 | 18 | let m := milliseconds() 19 | 20 | //var primes := (3..<1000).step(by:2).filter(n=>isPrime(n)) 21 | 22 | var primes := (3..<1000).step(by:2).filter(func(number) 23 | let sqrtNum := sqrt(number) 24 | for var i:=3 where i<= sqrtNum, i+=2 do 25 | if number % i = 0 then 26 | return False 27 | end 28 | end 29 | return True 30 | end) 31 | 32 | 33 | let ms := milliseconds() - m 34 | 35 | print(primes) 36 | 37 | print('In \(ms) ms.') 38 | 39 | -------------------------------------------------------------------------------- /interpreter/examples/primes3.gear: -------------------------------------------------------------------------------- 1 | 2 | use system 3 | 4 | func sieveOfErasthones(n) 5 | 6 | func filterMultiples(list, k) 7 | return list.filter(x=>(x <= k) | ((x > k) & ((x % k) <> 0))) 8 | end 9 | 10 | 11 | var listOfNum := (2..n).toArray() 12 | var i := 2 13 | 14 | while (i*i < n) & (i < n) do 15 | listOfNum := filterMultiples(listOfNum, i) 16 | i+=1 17 | end 18 | 19 | return listOfNum 20 | 21 | end 22 | 23 | 24 | 25 | let m := milliseconds() 26 | 27 | var s := sieveOfErasthones(10010) 28 | 29 | 30 | let ms := milliseconds() - m 31 | 32 | //print(s) 33 | print('In \(ms) ms.') 34 | 35 | //print(sieveOfErasthones(100)) 36 | 37 | print(s.last) 38 | 39 | -------------------------------------------------------------------------------- /interpreter/examples/primes4.gear: -------------------------------------------------------------------------------- 1 | //[n in [2..N] | forall m in {2..n - 1} | n mod m > 0] 2 | 3 | use system 4 | 5 | 6 | let m := milliseconds() 7 | 8 | let primes := 9 | {n for n in (3..<1000).step(by:2) where 10 | {m for m in (1..sqrt(n)).step(by:2) where n%m=0}.count=1} 11 | 12 | 13 | //let primes := (3..<1000).step(by:2) 14 | // .filter(n=>{m for m in (1..sqrt(n)).step(by:2) where n%m=0}.count=1) 15 | 16 | print(milliseconds()-m, ' ms') 17 | 18 | print(primes) 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /interpreter/examples/random.gear: -------------------------------------------------------------------------------- 1 | var number := randomLimit(100) + 1 2 | 3 | while True do 4 | print('Guess a number: ', terminator: '') 5 | 6 | ensure var guess := toNum(readln()) where guess <> Null else 7 | print('That`s not a number!') 8 | continue 9 | end 10 | 11 | if guess < number then 12 | print('Too low.') 13 | else 14 | if guess = number then 15 | print('You win!') 16 | break 17 | else 18 | print('Too high.') 19 | end 20 | end 21 | 22 | end 23 | 24 | -------------------------------------------------------------------------------- /interpreter/examples/range.gear: -------------------------------------------------------------------------------- 1 | // new range type 2 | 3 | use system 4 | 5 | let list := [0,1,2,3,4,5,6,7,8,9] 6 | 7 | for each i in Range(0,list.count-1) do 8 | print(i) 9 | end 10 | 11 | 12 | for each i in 0..x^2>3).map(x=>2*x) 5 | 6 | print(result) 7 | 8 | -------------------------------------------------------------------------------- /interpreter/examples/range2.gear: -------------------------------------------------------------------------------- 1 | use system 2 | 3 | var a := 1..10 4 | print(a) 5 | 6 | for each i in a do 7 | print(i) 8 | end 9 | 10 | a.forEach(func(n) print(n) end) 11 | let y := (10..15).forEach(func(n) print(n) end) 12 | print(a.filter(x=>x%2=0)) 13 | print(a.map(x=>x^2)) 14 | print(a.reduce(0, (x,y)=>x+y)) 15 | 16 | print((1..100).filter(x=>x%2=0)) 17 | 18 | var listOfEvens := (1..100).filter(x=>x%2=0) 19 | 20 | var factorial := n => (1..n).reduce(1, (x,y)=>x*y) 21 | print(factorial(10)) 22 | 23 | 24 | -------------------------------------------------------------------------------- /interpreter/examples/range3.gear: -------------------------------------------------------------------------------- 1 | // ranges 2 | 3 | use system 4 | 5 | for each ascii in Range(ord('a'), ord('z')) do 6 | print(chr(ascii), terminator: '|') 7 | end 8 | 9 | -------------------------------------------------------------------------------- /interpreter/examples/range4.gear: -------------------------------------------------------------------------------- 1 | 2 | use system 3 | 4 | 5 | for each i in -5..5 do 6 | print(i) 7 | end 8 | 9 | for each c in ord("A)..ord("Z) do 10 | print(chr(c)) 11 | end 12 | 13 | 14 | for each x in 5..<7 do 15 | print(x) 16 | end 17 | 18 | 19 | /* 20 | print(16>>2) 21 | print(16<<2) 22 | print(16^2) 23 | */ 24 | 25 | 26 | -------------------------------------------------------------------------------- /interpreter/examples/range5.gear: -------------------------------------------------------------------------------- 1 | 2 | use system 3 | 4 | var range := (1..20).step(by:2) 5 | 6 | print(range.iterator.stepBy) 7 | 8 | 9 | for each r in range do 10 | print(r) 11 | end 12 | 13 | for each i in (0..20).step(by:2) do 14 | print(i) 15 | end 16 | 17 | -------------------------------------------------------------------------------- /interpreter/examples/roots.gear: -------------------------------------------------------------------------------- 1 | 2 | let ta := [8, 27, 64, 125] 3 | 4 | func nthRoot(b,n) 5 | return exp((1/n)*ln(b)) 6 | end 7 | 8 | for var v:=0 where v<= ['French fries'] 19 | groceries.add(value: 'Mushrooms') 20 | print(groceries) 21 | 22 | var a := [] 23 | a.add(value: 1) 24 | print(a) 25 | 26 | //var emptyDict := Dictionary() 27 | var emptyDict := [:] 28 | emptyDict.add(key: 1, value: 'One') 29 | print(emptyDict) 30 | 31 | 32 | var smileys := ['smile': '😀', 'saint': '😇'] 33 | smileys.add(key: 'lol', value: '🤣') 34 | smileys.add(key: 'cool', value: '😎') 35 | smileys.add(key: 'cry', value: '😭') 36 | print(smileys) 37 | 38 | -------------------------------------------------------------------------------- /interpreter/examples/smileys.gear: -------------------------------------------------------------------------------- 1 | use system 2 | let smileys := ['😄', '😘', '😛', '🤨', '😏'] 3 | 4 | for each smiley in smileys do 5 | print('Smiley \(smiley) has ascii code \(ord(smiley)).') 6 | end 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /interpreter/examples/speed.gear: -------------------------------------------------------------------------------- 1 | // speed test list building 2 | 3 | //list ><= [transform(item)] 4 | //list.add(value: transform(item)) 5 | //listAdd(list, transform(item)) 6 | 7 | use system 8 | 9 | //let m := milliseconds() 10 | 11 | /* 12 | var c := [] 13 | for each i in 0..<10000 do // 276 ms (2660ms for 100000) 14 | listAdd(c, i) 15 | end 16 | */ 17 | //print(milliseconds()-m) 18 | 19 | /* 20 | var d := [] 21 | for var i := 0 where i<10000, i+=1 do // 76 ms (775ms for 100000) 22 | listAdd(d, i) 23 | end 24 | */ 25 | /* 26 | var b := [] 27 | for each i in 0..<10000 do // 352 ms (3394ms for 100000) 28 | b.add(value: i) 29 | end 30 | */ 31 | /* 32 | var a := [] 33 | for each i in 0..<10000 do // 2444 ms 34 | a ><= [i] 35 | end 36 | */ 37 | 38 | let m := milliseconds() 39 | 40 | var c := [] 41 | for each i in 0..<1000 where i%2=0 do // 276 ms (2660ms for 100000) 42 | c.add(value: i^2) 43 | end 44 | 45 | print(milliseconds()-m) 46 | 47 | 48 | let n := milliseconds() 49 | 50 | //var list := { n^2 for n in 0..<10000 } // 314ms (3140ms for 100000) 51 | 52 | var list := {n^2 for n in 0..<1000 where n%2=0 } 53 | 54 | print(milliseconds()-n) 55 | 56 | print('====================') 57 | print(c) 58 | print('====================') 59 | print(list) 60 | 61 | // conclusion listAdd function is quickest 62 | // and normal for loop is almost 4 times quicker than for each 63 | 64 | 65 | -------------------------------------------------------------------------------- /interpreter/examples/stack.gear: -------------------------------------------------------------------------------- 1 | // stack implementation 2 | use system 3 | 4 | class Stack 5 | let items := [] 6 | func push(item) 7 | self.items.add(value: item) 8 | end 9 | func pop() 10 | self.items.remove(value: self.items.last) 11 | end 12 | val top := self.items.last 13 | end 14 | 15 | var stack := Stack() 16 | 17 | stack.push(99) 18 | stack.push(201) 19 | stack.push(pi()) 20 | //stack.push('hello') 21 | stack.push(777) 22 | 23 | for each item in stack.items do 24 | print(item) 25 | end 26 | 27 | print('last: ', stack.items.last) 28 | 29 | 30 | print(stack.top) 31 | stack.pop() 32 | stack.pop() 33 | print(stack.top) 34 | 35 | for each item in stack.items do 36 | print(item) 37 | end 38 | 39 | -------------------------------------------------------------------------------- /interpreter/examples/standard.gear: -------------------------------------------------------------------------------- 1 | print(trunc(3.14)) 2 | print(date()) 3 | print(time()) 4 | print(now()) 5 | print(today()) 6 | 7 | print(4 | 2) // binary: 100 or 010 = 110 8 | -------------------------------------------------------------------------------- /interpreter/examples/steps.gear: -------------------------------------------------------------------------------- 1 | // steps in ranges 2 | use system 3 | 4 | for var i:=0 where i<10, i+=2 do 5 | print(i) 6 | end 7 | print() 8 | 9 | for each i in 0..<10 where i%2=0 do 10 | print(i) 11 | end 12 | print() 13 | 14 | for each i in (0..<10).step(by:2) do 15 | print(i) 16 | end 17 | print() 18 | 19 | for each i in Range(0,9).step(by:2) do 20 | print(i) 21 | end 22 | print() 23 | 24 | print((0..<10).step(by:2).toArray()) 25 | 26 | let a := [0,1,2,3,4,5,6,7,8,9,10] 27 | a.forEach(func(n) print(n) end) 28 | //[0,1,2,3,4,5,6,7,8,9,10].forEach(func(n) print(n) end) 29 | 30 | print() 31 | let b := 0..<10 32 | b.step(by:2).forEach(func(n) print(n) end) 33 | -------------------------------------------------------------------------------- /interpreter/examples/str.gear: -------------------------------------------------------------------------------- 1 | var s := 'Hello it''s my turn now.\n\tHere!' 2 | print(s) 3 | 4 | var x := '' 5 | print(x) 6 | x := 'it''s me' 7 | print(x) 8 | 9 | -------------------------------------------------------------------------------- /interpreter/examples/str1.gear: -------------------------------------------------------------------------------- 1 | 2 | var s := 'it''s' + 'me' 3 | print(s) 4 | 5 | -------------------------------------------------------------------------------- /interpreter/examples/str2.gear: -------------------------------------------------------------------------------- 1 | var s := 'it''s' + 'me' 2 | print(s) 3 | 4 | -------------------------------------------------------------------------------- /interpreter/examples/str3.gear: -------------------------------------------------------------------------------- 1 | var s := '' 2 | s := s + 'it''s' + ' me' 3 | print(s) 4 | 5 | -------------------------------------------------------------------------------- /interpreter/examples/string.gear: -------------------------------------------------------------------------------- 1 | // test strings 2 | 3 | let y := 3 4 | var s := 'Hello it''s my turn now.\n\tHere!' 5 | 6 | var s2 := '' 7 | s2 := 'that''s me!' 8 | print('\(y)') 9 | print(s) 10 | print(s2) 11 | 12 | print('It''s me') 13 | 14 | -------------------------------------------------------------------------------- /interpreter/examples/switch.gear: -------------------------------------------------------------------------------- 1 | // switch with is 2 | 3 | class Root 4 | var name := 'Root' 5 | end 6 | 7 | class First (Root) 8 | end 9 | 10 | class Second (Root) 11 | end 12 | 13 | class Third (Second) 14 | end 15 | class Fourth 16 | end 17 | 18 | var sec := Second() 19 | 20 | print('Start: ', sec.name) 21 | 22 | switch sec 23 | case is Root: print('Root') 24 | case is First: print('First') 25 | case is Second: print('Second') 26 | case is Third: print('Third') 27 | else 28 | print('None of the above') 29 | end 30 | 31 | 32 | -------------------------------------------------------------------------------- /interpreter/examples/switchregr.gear: -------------------------------------------------------------------------------- 1 | let char := 'r' 2 | switch char 3 | case 'a', 'e', 'i', 'o', 'u': 4 | print('\(char) is a vowel with ascii value \(ord(char)).') 5 | case 'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 6 | 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z': 7 | print('\(char) is a consonant with ascii value \(ord(char)).') 8 | else 9 | print('\(char) is not a vowel nor a consonant. Ascii value: \(ord(char)).') 10 | end 11 | // r is a consonant with ascii value 114. 12 | 13 | -------------------------------------------------------------------------------- /interpreter/examples/test.gear: -------------------------------------------------------------------------------- 1 | let userName := '12345678?' 2 | let chars := Array(userName) 3 | print(chars) 4 | 5 | -------------------------------------------------------------------------------- /interpreter/examples/trait.gear: -------------------------------------------------------------------------------- 1 | // traits 2 | 3 | use system 4 | 5 | trait ValidatesUsername 6 | 7 | func validUNChars() 8 | var result := [] 9 | for each ascii in Range(48, 57) do 10 | result.add(value: chr(ascii)) 11 | end 12 | for each ascii in Range(65, 90) do 13 | result.add(value: chr(ascii)) 14 | end 15 | for each ascii in Range(97, 122) do 16 | result.add(value: chr(ascii)) 17 | end 18 | return result 19 | end 20 | 21 | func isUsernameValid(username) 22 | let chars := Array(username) 23 | for each char in chars do 24 | ensure self.validUNChars().contains(value: char) else 25 | return False 26 | end 27 | end 28 | return if chars.count < 8 then False else True 29 | end 30 | 31 | end 32 | 33 | trait ValidatesPassword 34 | 35 | func validPWChars() 36 | var result := [] 37 | for each char in Range(34, 125) do 38 | result.add(value: chr(char)) 39 | end 40 | return result 41 | end 42 | 43 | func isPasswordValid(password) 44 | let chars := Array(password) 45 | for each char in chars do 46 | ensure self.validPWChars().contains(value: char) else 47 | return False 48 | end 49 | end 50 | return if chars.count < 8 then False else True 51 | end 52 | 53 | end 54 | 55 | class Login: ValidatesUsername, ValidatesPassword 56 | var userName := '' 57 | var passWord := '' 58 | 59 | init(userName, passWord) 60 | self.userName := userName 61 | self.passWord := passWord 62 | end 63 | 64 | func loginEntered() 65 | ensure self.isUsernameValid(self.userName) else 66 | print('Wrong user name') 67 | return False 68 | end 69 | ensure self.isPasswordValid(self.passWord) else 70 | print('Wrong password') 71 | return False 72 | end 73 | return True 74 | end 75 | 76 | end 77 | 78 | print('user name: ', terminator: '') 79 | let userName := readln() 80 | print('password : ', terminator: '') 81 | let passWord := readln() 82 | 83 | var login := Login(userName, passWord) 84 | 85 | print(if login.loginEntered() then 'Login correct' else 'Login incorrect') 86 | 87 | 88 | -------------------------------------------------------------------------------- /interpreter/examples/tuple.gear: -------------------------------------------------------------------------------- 1 | 2 | // tuples 3 | 4 | let one := (1, 'one') 5 | print(one) 6 | 7 | let other := one 8 | print(other) 9 | 10 | let a := 6, b := 'ten', c := True 11 | 12 | let some := (a,b,c) 13 | print(some) 14 | 15 | var s := some.2 16 | print(s) 17 | 18 | some.2 := 'eleven' 19 | print(some) 20 | 21 | 22 | func test() 23 | return (2, 'two', 'twelve') 24 | end 25 | 26 | var x := test() 27 | print(x) 28 | 29 | let p := test() 30 | print(p) 31 | p.3 := 'fifteen' 32 | print(p) 33 | 34 | var w := (x=>x^2, x=>x^0.5) 35 | 36 | print(w.1(5)) // 25 37 | print(w.2(16)) // 4 38 | 39 | -------------------------------------------------------------------------------- /interpreter/examples/tuples.gear: -------------------------------------------------------------------------------- 1 | 2 | use system 3 | 4 | func calculate(.scores) 5 | var min := 0, max := 0, sum := 0, avg := 0 6 | 7 | for each score in scores do 8 | if score > max then 9 | max := score 10 | elseif score < max then 11 | min := score 12 | end 13 | sum += score 14 | end 15 | avg := sum / scores.count 16 | 17 | return (min, max, sum, avg) 18 | end 19 | 20 | let statistics := calculate(scores: [6, 7, 8, 9, 5, 4, 10, 3]) 21 | print('min: \(statistics.1)') 22 | print('max: \(statistics.2)') 23 | print('sum: \(statistics.3)') 24 | print('avg: \(statistics.4)') 25 | 26 | -------------------------------------------------------------------------------- /interpreter/examples/twice.gear: -------------------------------------------------------------------------------- 1 | 2 | 3 | let twice := (f, x) => f(f(x)) 4 | 5 | let addTwo := x => x + 2 6 | 7 | print(twice(addTwo, 2)) // => 6 8 | 9 | 10 | -------------------------------------------------------------------------------- /interpreter/examples/vardecl.gear: -------------------------------------------------------------------------------- 1 | // test var declarations 2 | 3 | var x:=1, y:=2, z:=3, s:='Saturn' 4 | let v:=4, w:=5, p:='Pluto' 5 | 6 | print(x,y,z,s,v,w,p) 7 | 8 | x:=9 9 | print(x,y,z) 10 | 11 | class Point 12 | var x:=0, y:=0 13 | init(.x, .y) 14 | self.x:=x 15 | self.y:=y 16 | end 17 | func distance(to point) 18 | return sqrt((point.x-self.x)^2 + (point.y-self.y)^2) 19 | end 20 | end 21 | 22 | var p0 := Point(), p1 := Point(x:1,y:1), p2 := Point(x:3,y:4) 23 | 24 | print(p1.distance(to: p0)) 25 | print(p2.distance(to: p0)) 26 | 27 | -------------------------------------------------------------------------------- /interpreter/examples/words.gear: -------------------------------------------------------------------------------- 1 | 2 | dictionary Words 3 | [:] 4 | val count := length(self) 5 | func toString() => self 6 | end 7 | var words := Words() 8 | 9 | words['pair'] := 'couple' 10 | words['collection'] := 'group' 11 | print(words.toString()) 12 | 13 | -------------------------------------------------------------------------------- /interpreter/gearlib/arrays.gear: -------------------------------------------------------------------------------- 1 | extension Array 2 | val count := length(self) 3 | val first := listFirst(self) 4 | val last := listLast(self) 5 | 6 | func set(.size, .fillChar) => listInit(self, size, fillChar) 7 | func add(.value) => listAdd(self, value) 8 | func add(.list) => listAddList(self, list) 9 | func insert(at index, .value) => listInsert(self, index, value) 10 | func delete(.index) 11 | listDelete(self, index) 12 | end 13 | func remove(.value) => listRemove(self, value) 14 | func extract(.value) => listExtract(self, value) 15 | func contains(.value) => listContains(self, value) 16 | func index(of value) => listIndexOf(self, value) 17 | func retrieve(.index) => listRetrieve(self, index) 18 | func clear() 19 | listClear(self) 20 | end 21 | end 22 | 23 | class ArrayIterator 24 | let list := Null 25 | var index := 0 26 | let count := Null 27 | 28 | init(list) 29 | self.list := list 30 | self.count := length(list) 31 | end 32 | 33 | val hasNext := self.index < self.count 34 | 35 | val next 36 | var nextItem := self.list [self.index] 37 | self.index +=1 38 | return nextItem 39 | end 40 | end 41 | 42 | extension Array 43 | val iterator := ArrayIterator(self) 44 | end 45 | 46 | extension Array 47 | 48 | func reduce(initialValue, nextValue) 49 | var result := initialValue 50 | 51 | for var i := 0 where i < length(self), i+=1 do 52 | result := nextValue(result, self[i]) 53 | end 54 | return result 55 | end 56 | 57 | func filter(includeElement) 58 | var result := [] 59 | for var i := 0 where i < length(self), i+=1 do 60 | if includeElement(self[i]) then 61 | result.add(value: self[i]) 62 | end 63 | end 64 | return result 65 | end 66 | 67 | func map(transform) 68 | var result := [] 69 | for var i := 0 where i < length(self), i+=1 do 70 | result.add(value: transform(self[i])) 71 | end 72 | return result 73 | end 74 | 75 | func flatMap(transform) 76 | return self.map(transform).reduce([],(x,y)=>x> Null then 9 | for each item in input where include(item) do 10 | listAdd(result, transform(item)) 11 | end 12 | else 13 | for each item in input do 14 | listAdd(result, transform(item)) 15 | end 16 | end 17 | return result 18 | end 19 | 20 | -------------------------------------------------------------------------------- /interpreter/gearlib/dictionaries.gear: -------------------------------------------------------------------------------- 1 | 2 | extension Dictionary 3 | 4 | val count := length(self) 5 | 6 | func toString() => self 7 | 8 | func add(.key, .value) => dictAdd(self, key, value) 9 | func add(.list) => dictAddList(self, list) 10 | 11 | func delete(.key) 12 | dictDelete(self, key) 13 | end 14 | 15 | func contains(.key) => dictContainsKey(self, key) 16 | func contains(.value) => dictContainsValue(self, value) 17 | 18 | func value(of key) => dictValueOf(self, key) 19 | func key(of value) => dictKeyOf(self, value) 20 | 21 | func set(.sorted) 22 | dictSetSorted(self, sorted) 23 | end 24 | func sort() 25 | dictSort(self) 26 | end 27 | 28 | func clear() 29 | dictClear(self) 30 | end 31 | end 32 | 33 | extension Dictionary 34 | val keys := dictKeys(self) 35 | val values := dictValues(self) 36 | end 37 | 38 | class DictionaryIterator 39 | let keys := Null, values := Null 40 | var index := 0 41 | 42 | init(list) 43 | self.keys := list.keys 44 | self.values := list.values 45 | end 46 | 47 | func makeItem(key, value) 48 | class Item 49 | let key := Null, value := Null 50 | init(key, value) 51 | self.key := key 52 | self.value := value 53 | end 54 | end 55 | return Item(key, value) 56 | end 57 | 58 | val hasNext := self.index < length(self.keys) 59 | 60 | val next 61 | let nextItem := self.makeItem( 62 | self.keys[self.index], self.values[self.index]) 63 | self.index +=1 64 | return nextItem 65 | end 66 | end 67 | 68 | extension Dictionary 69 | val iterator := DictionaryIterator(self) 70 | end 71 | 72 | -------------------------------------------------------------------------------- /interpreter/gearlib/ranges.gear: -------------------------------------------------------------------------------- 1 | 2 | class RangeIterator 3 | var index := 0, 4 | range := Null, 5 | stepBy := 1 6 | 7 | init(range) 8 | self.range := range 9 | self.index := range.from 10 | self.stepBy := range.stepBy 11 | end 12 | 13 | val hasNext := self.index <= self.range.to 14 | 15 | val next 16 | var result := self.index 17 | self.index += self.stepBy 18 | return result 19 | end 20 | end 21 | 22 | class Range 23 | var from := Null, 24 | to := Null, 25 | stepBy := 1 26 | 27 | init(from, to) 28 | self.from := from 29 | self.to := to 30 | end 31 | 32 | val iterator := RangeIterator(self) 33 | end 34 | 35 | extension Range 36 | func step(.by) 37 | self.stepBy := by 38 | return self 39 | end 40 | end 41 | 42 | extension Range 43 | func toArray() 44 | var result := [] 45 | for each item in self do 46 | listAdd(result, item) 47 | end 48 | return result 49 | end 50 | 51 | func reduce(initialValue, nextValue) 52 | var result := initialValue 53 | for each item in self do 54 | result := nextValue(result, item) 55 | end 56 | return result 57 | end 58 | 59 | func filter(includeElement) 60 | var result := [] 61 | for each item in self where includeElement(item) do 62 | listAdd(result, item) 63 | end 64 | return result 65 | end 66 | 67 | func map(transform) 68 | var result := [] 69 | for each item in self do 70 | listAdd(result, transform(item)) 71 | end 72 | return result 73 | end 74 | 75 | func forEach(function) 76 | for each item in self do 77 | function(item) 78 | end 79 | end 80 | 81 | func contains(.value) 82 | if (value >= self.from) & (value <= self.to) then 83 | return True 84 | end 85 | return False 86 | end 87 | end 88 | 89 | -------------------------------------------------------------------------------- /interpreter/gearlib/strings.gear: -------------------------------------------------------------------------------- 1 | //module strings.gear 2 | // standard string routines 3 | 4 | // copies part of a string from start for count characters 5 | func copy(.string, .start, .count) 6 | var result := '' 7 | var len := length(string) 8 | if len > start+count then 9 | len := start+count 10 | end 11 | for var i := start where i '@[\(self.line),\(self.col)]: \(self.msg)' 14 | end 15 | 16 | let Errors := [] 17 | 18 | func error(token, msg) 19 | Errors.add(value: Error(token.line, token.col, msg)) 20 | end 21 | 22 | -------------------------------------------------------------------------------- /interpreter/lexer-parser/main.gear: -------------------------------------------------------------------------------- 1 | use reader 2 | use lexer 3 | use parser 4 | use ast 5 | use errors 6 | use printer 7 | 8 | print('Enter file name (incl path): ') 9 | let file := readln() 10 | 11 | let parser := Parser(Lexer(Reader(file))) 12 | 13 | let ast := parser.parse() 14 | 15 | if Errors.count > 0 then 16 | print('*** Errors ***') 17 | for each error in Errors do 18 | print(error.toString()) 19 | end 20 | else 21 | Printer(ast).write() 22 | print('No errors.') 23 | end 24 | 25 | 26 | -------------------------------------------------------------------------------- /interpreter/lexer-parser/printer.gear: -------------------------------------------------------------------------------- 1 | 2 | use system 3 | use visitor 4 | use strings 5 | 6 | class Printer(Visitor) 7 | let increase := 2 8 | var indent := '' 9 | let tree := Null 10 | init(tree) 11 | self.tree := tree 12 | end 13 | 14 | func incIndent() 15 | self.indent := string(of: ' ', count: length(self.indent) + self.increase) 16 | end 17 | 18 | func decIndent() 19 | self.indent := string(of: ' ', count: length(self.indent) - self.increase) 20 | end 21 | 22 | func write() 23 | self.visit(self.tree) 24 | end 25 | 26 | func visitAst(Ast) 27 | print(self.indent + Ast.className) 28 | end 29 | 30 | func visitSyntax(syntax) 31 | self.incIndent() 32 | self.visitAst(syntax) 33 | print(self.indent + 'No. of productions: \(syntax.productions.count)') 34 | for each production in syntax.productions do 35 | self.visit(production) 36 | end 37 | self.decIndent() 38 | end 39 | 40 | func visitProduction(production) 41 | self.incIndent() 42 | self.visitAst(production) 43 | self.visit(production.left) 44 | self.visit(production.right) 45 | self.decIndent() 46 | end 47 | 48 | func visitExpression(expression) 49 | self.incIndent() 50 | self.visitAst(expression) 51 | for each term in expression.terms do 52 | self.visit(term) 53 | end 54 | self.decIndent() 55 | end 56 | 57 | func visitTerm(term) 58 | self.incIndent() 59 | self.visitAst(term) 60 | for each factor in term.factors do 61 | self.visit(factor) 62 | end 63 | self.decIndent() 64 | end 65 | 66 | func visitGroup(group) 67 | self.incIndent() 68 | self.visitAst(group) 69 | self.visit(group.expression) 70 | self.decIndent() 71 | end 72 | 73 | func visitOption(option) 74 | self.incIndent() 75 | self.visitAst(option) 76 | self.visit(option.expression) 77 | self.decIndent() 78 | end 79 | 80 | func visitRepetition(repetition) 81 | self.incIndent() 82 | self.visitAst(repetition) 83 | self.visit(repetition.expression) 84 | self.decIndent() 85 | end 86 | 87 | func visitIdentifier(identifier) 88 | self.incIndent() 89 | print(self.indent + 'Identifier: \(identifier.letters)') 90 | self.decIndent() 91 | end 92 | 93 | func visitLiteral(literal) 94 | self.incIndent() 95 | print(self.indent + 'Literal: \(literal.value)') 96 | self.decIndent() 97 | end 98 | 99 | end 100 | 101 | -------------------------------------------------------------------------------- /interpreter/lexer-parser/reader.gear: -------------------------------------------------------------------------------- 1 | 2 | use system 3 | use errors 4 | 5 | let fileEnding := chr(4) 6 | 7 | class Reader 8 | var fileName := '', fileIndex := 0 9 | var bytes := [] 10 | var chars := [] 11 | var index := 1, size := 0 12 | 13 | init(fileName) 14 | self.fileName := fileName 15 | self.bytes := self.readFile() 16 | if self.bytes <> Null then 17 | self.size := self.bytes.count 18 | self.chars := self.toChars() 19 | end 20 | end 21 | 22 | func readFile() 23 | ensure let file := fileOpen(self.fileName, forReading) where file <> -1 else 24 | error(Token(), 'Path/file combination does not exist.') 25 | return Null 26 | end 27 | let input := fileRead(file) // note byte array 28 | fileClose(file) 29 | return input 30 | end 31 | 32 | func toChars() 33 | return self.bytes.map(c=>chr(c)) 34 | end 35 | 36 | func nextChar() 37 | if self.index < self.size then 38 | let result := self.chars[self.index] 39 | self.index +=1 // move to next char 40 | return result 41 | end 42 | return fileEnding 43 | end 44 | 45 | val peekChar 46 | if self.index <= self.size then 47 | return self.chars[self.index] // read next char, don't move index 48 | end 49 | return fileEnding 50 | end 51 | 52 | end 53 | -------------------------------------------------------------------------------- /interpreter/lexer-parser/readme.md: -------------------------------------------------------------------------------- 1 | a lexer parser for parsing ebnf text 2 | written in Gear 3 | -------------------------------------------------------------------------------- /interpreter/lexer-parser/token.gear: -------------------------------------------------------------------------------- 1 | 2 | use tokentype 3 | 4 | class Token 5 | var type := TokenType.None 6 | var lexeme := '', value := '' 7 | var line := 0, col := 0 8 | 9 | init(type, lexeme, value, line, col) 10 | self.type := type 11 | self.lexeme := lexeme 12 | self.value := value 13 | self.line := line 14 | self.col := col 15 | end 16 | 17 | val toString := 18 | '\(self.type.toString); \(self.lexeme); [\(self.line),\(self.col)]' 19 | end 20 | 21 | -------------------------------------------------------------------------------- /interpreter/lexer-parser/tokentype.gear: -------------------------------------------------------------------------------- 1 | 2 | use system 3 | 4 | enum TokenType 5 | (Identifier = 'Identifier', Literal = 'Literal' 6 | 7 | case Symbols: 8 | OpenBrack='[', CloseBrack=']', OpenBrace='{', CloseBrace='}', 9 | OpenParen='(', CloseParen=')', 10 | Definition='=', Alternative='|', Termination='.', Special='?' 11 | 12 | case SpecialHandling: 13 | EOF='EOF', Error='Error' 14 | 15 | None 16 | ) 17 | 18 | val toString := self.value 19 | end 20 | 21 | let factorStartSet := [TokenType.Identifier, TokenType.Literal, 22 | TokenType.OpenParen, TokenType.OpenBrack, TokenType.OpenBrace] 23 | 24 | let prodSychSet := [TokenType.Definition, TokenType.Identifier, 25 | TokenType.Literal, TokenType.EOF] 26 | 27 | -------------------------------------------------------------------------------- /interpreter/lexer-parser/visitor.gear: -------------------------------------------------------------------------------- 1 | 2 | class Visitor 3 | 4 | func visit(node) 5 | let name := 'visit' + node.className 6 | let function := method(self, name) 7 | 8 | return function(node) 9 | end 10 | 11 | end 12 | 13 | -------------------------------------------------------------------------------- /interpreter/readme: -------------------------------------------------------------------------------- 1 | empty 2 | -------------------------------------------------------------------------------- /interpreter/uArrayIntf.pas: -------------------------------------------------------------------------------- 1 | unit uArrayIntf; 2 | 3 | { This unit contains the interfaces needed for TArrayClass and TArrayInstance. 4 | 5 | Copyright (C) 2018 J. de Haan jdehaan2014@gmail.com 6 | 7 | This source is free software; you can redistribute it and/or modify it under the terms 8 | of the GNU General Public License as published by the Free Software Foundation; either 9 | version 2 of the License, or (at your option) any later version. 10 | 11 | This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 12 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 13 | PURPOSE. See the GNU General Public License for more details. 14 | 15 | A copy of the GNU General Public License is available on the World Wide Web at 16 | . You can also obtain it by writing to the Free 17 | Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA. 18 | } 19 | 20 | {$mode objfpc}{$H+} 21 | 22 | interface 23 | 24 | uses 25 | Classes, SysUtils, uCallable, uAST, Variants, uMembers, uCollections, uToken; 26 | 27 | type 28 | 29 | IArrayable = Interface(ICallable) 30 | ['{1A6EC506-9318-F69B-0563-830506C351F7}'] 31 | procedure ExtendWith(Members: TMembers); 32 | end; 33 | 34 | TArrayElements = specialize TArray; 35 | 36 | IArrayInstance = Interface 37 | ['{5C2DF1A9-88BC-8FFE-B6F2-6C3DCF535601}'] 38 | function GetMember(Ident: TIdent): Variant; 39 | function getElements: TArrayElements; 40 | function getCount: LongInt; 41 | property Elements: TArrayElements read getElements; 42 | property Count: LongInt read getCount; 43 | function getItem(i: integer): Variant; 44 | procedure setItem(i: integer; AValue: Variant); 45 | property Items[i:integer]: Variant read getItem write setItem; default; 46 | function TypeName: String; 47 | function Get(i: Integer; Token: TToken): Variant; 48 | procedure Put(i: Integer; Value: Variant; Token: TToken); 49 | procedure Add(const AValue: Variant); 50 | procedure Insert(const i: Integer; const AValue: Variant; Token: TToken); 51 | procedure Delete(const AValue: Variant; Token: TToken); 52 | function Contains(const AValue: Variant): Boolean; 53 | function IndexOf(const AValue: Variant): Variant; 54 | function Retrieve(const AIndex: Integer; Token: TToken): Variant; 55 | end; 56 | 57 | implementation 58 | 59 | end. 60 | 61 | -------------------------------------------------------------------------------- /interpreter/uCallable.pas: -------------------------------------------------------------------------------- 1 | unit uCallable; 2 | 3 | { This unit contains the ICallable interface, needed for function calls. 4 | 5 | Copyright (C) 2018 J. de Haan jdehaan2014@gmail.com 6 | 7 | This source is free software; you can redistribute it and/or modify it under the terms 8 | of the GNU General Public License as published by the Free Software Foundation; either 9 | version 2 of the License, or (at your option) any later version. 10 | 11 | This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 12 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 13 | PURPOSE. See the GNU General Public License for more details. 14 | 15 | A copy of the GNU General Public License is available on the World Wide Web at 16 | . You can also obtain it by writing to the Free 17 | Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA. 18 | } 19 | 20 | {$mode objfpc}{$H+} 21 | 22 | interface 23 | 24 | uses 25 | Classes, SysUtils, uCollections, uInterpreter, uToken, uAST, Variants; 26 | 27 | type 28 | TCallArg = class 29 | Value: Variant; 30 | Ident: TIdent; 31 | Token: TToken; 32 | constructor Create(AValue: Variant; AIdent: TIdent; AToken: TToken); 33 | end; 34 | 35 | TArgList = specialize TArrayObj; 36 | 37 | ICallable = interface 38 | ['{EBA5469A-1CA1-FB54-0D6F-60889AFA4679}'] 39 | function Call(Token: TToken; Interpreter: TInterpreter; 40 | ArgList: TArgList): Variant; 41 | function toString: String; 42 | end; 43 | 44 | IValuable = interface(ICallable) 45 | ['{C5B7F7F5-3E31-AE0F-C7E2-FC4B56B77224}'] 46 | end; 47 | 48 | implementation 49 | 50 | constructor TCallArg.Create(AValue: Variant; AIdent: TIdent; AToken: TToken); 51 | begin 52 | Value := AValue; 53 | Ident := AIdent; 54 | Token := AToken; 55 | end; 56 | 57 | end. 58 | 59 | -------------------------------------------------------------------------------- /interpreter/uClassIntf.pas: -------------------------------------------------------------------------------- 1 | unit uClassIntf; 2 | 3 | { This unit contains the IClassable interface, needed for class calls. 4 | 5 | Copyright (C) 2018 J. de Haan jdehaan2014@gmail.com 6 | 7 | This source is free software; you can redistribute it and/or modify it under the terms 8 | of the GNU General Public License as published by the Free Software Foundation; either 9 | version 2 of the License, or (at your option) any later version. 10 | 11 | This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 12 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 13 | PURPOSE. See the GNU General Public License for more details. 14 | 15 | A copy of the GNU General Public License is available on the World Wide Web at 16 | . You can also obtain it by writing to the Free 17 | Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA. 18 | } 19 | 20 | {$mode objfpc}{$H+} 21 | 22 | interface 23 | 24 | uses 25 | Classes, SysUtils, uCallable, uAST, uMembers; 26 | 27 | type 28 | 29 | IClassable = interface(ICallable) 30 | ['{230E841B-D57B-F5F8-4DD3-224B74645A17}'] 31 | procedure ExtendWith(Members: TMembers); 32 | function getName: String; 33 | property Name: String read getName; 34 | end; 35 | 36 | IGearInstance = Interface 37 | ['{6E9625B1-8DAD-EC3B-57E5-80D360CC7B67}'] 38 | function toString: String; 39 | function GetMember(Ident: TIdent): Variant; 40 | procedure SetField(Ident: TIdent; Value: Variant); 41 | function isConstant(Ident: TIdent): Boolean; 42 | function getClassName: String; 43 | property ClassName: String read getClassName; 44 | end; 45 | 46 | ITraitable = interface 47 | ['{4CEE3AA1-2D73-E3C0-DA25-6C6E52BCD1D1}'] 48 | function getIdent: TIdent; 49 | function getMethods: TMethodTable; 50 | function getValues: TValueTable; 51 | property Ident: TIdent read getIdent; 52 | property Methods: TMethodTable read getMethods; 53 | property Values: TValueTable read getValues; 54 | end; 55 | 56 | implementation 57 | 58 | end. 59 | 60 | -------------------------------------------------------------------------------- /interpreter/uDictIntf.pas: -------------------------------------------------------------------------------- 1 | unit uDictIntf; 2 | 3 | { This unit contains the interfaces needed for TDictClass and TDictInstance. 4 | 5 | Copyright (C) 2019 J. de Haan jdehaan2014@gmail.com 6 | 7 | This source is free software; you can redistribute it and/or modify it under the terms 8 | of the GNU General Public License as published by the Free Software Foundation; either 9 | version 2 of the License, or (at your option) any later version. 10 | 11 | This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 12 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 13 | PURPOSE. See the GNU General Public License for more details. 14 | 15 | A copy of the GNU General Public License is available on the World Wide Web at 16 | . You can also obtain it by writing to the Free 17 | Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA. 18 | } 19 | 20 | {$mode objfpc}{$H+} 21 | 22 | interface 23 | 24 | uses 25 | Classes, SysUtils, uCallable, uAST, Variants, uMembers, uCollections, uToken; 26 | 27 | type 28 | 29 | IDictionable = interface(ICallable) 30 | ['{F461B1D0-B563-695D-455C-A3606F6DE48F}'] 31 | procedure ExtendWith(Members: TMembers); 32 | end; 33 | 34 | TDictElements = specialize TDictionary; 35 | 36 | IDictInstance = Interface 37 | ['{A467BC62-AC8F-F5F2-6691-E2586512EE21}'] 38 | function getCount: LongInt; 39 | function getElements: TDictElements; 40 | property Elements: TDictElements read getElements; 41 | property Count: LongInt read getCount; 42 | function GetMember(Ident: TIdent): Variant; 43 | function TypeName: String; 44 | function Get(Key: Variant; Token: TToken): Variant; 45 | procedure Put(Key: Variant; Value: Variant; Token: TToken); 46 | procedure Add(const AKey, AValue: Variant); 47 | procedure Insert(const i: Integer; const AKey, AValue: Variant; Token: TToken); 48 | procedure Delete(const AValue: Variant; Token: TToken); 49 | function Contains(const AKey: Variant): Boolean; 50 | function IndexOf(const AKey: Variant): Variant; 51 | function Retrieve(const AKey: Variant; Token: TToken): Variant; 52 | function Keys: Variant; 53 | function Values: Variant; 54 | end; 55 | 56 | implementation 57 | 58 | end. 59 | 60 | -------------------------------------------------------------------------------- /interpreter/uEnumIntf.pas: -------------------------------------------------------------------------------- 1 | unit uEnumIntf; 2 | 3 | { This unit contains the interfaces needed for TEnumClass and TEnumInstance. 4 | 5 | Copyright (C) 2019 J. de Haan jdehaan2014@gmail.com 6 | 7 | This source is free software; you can redistribute it and/or modify it under the terms 8 | of the GNU General Public License as published by the Free Software Foundation; either 9 | version 2 of the License, or (at your option) any later version. 10 | 11 | This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 12 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 13 | PURPOSE. See the GNU General Public License for more details. 14 | 15 | A copy of the GNU General Public License is available on the World Wide Web at 16 | . You can also obtain it by writing to the Free 17 | Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA. 18 | } 19 | 20 | {$mode objfpc}{$H+} 21 | 22 | interface 23 | 24 | uses 25 | Classes, SysUtils, uAST, Variants, uMembers, uToken, uArrayIntf; 26 | 27 | type 28 | 29 | IEnumable = Interface 30 | ['{0C787B09-3EB8-C197-D539-47B40762797D}'] 31 | procedure ExtendWith(Members: TMembers); 32 | function isCase(Name: String): Boolean; 33 | function ElementList: IArrayInstance; 34 | end; 35 | 36 | IEnumInstance = Interface 37 | ['{1F7D0C58-2866-4A85-7FA2-E36590303912}'] 38 | function GetMember(Ident: TIdent): Variant; 39 | function EnumName: String; 40 | function ElemName: String; 41 | function ElemValue: Variant; 42 | function ElemSetName: String; 43 | end; 44 | 45 | implementation 46 | 47 | end. 48 | 49 | -------------------------------------------------------------------------------- /interpreter/uMembers.pas: -------------------------------------------------------------------------------- 1 | unit uMembers; 2 | 3 | { This unit contains the transport record TMembers. 4 | 5 | Copyright (C) 2018 J. de Haan jdehaan2014@gmail.com 6 | 7 | This source is free software; you can redistribute it and/or modify it under the terms 8 | of the GNU General Public License as published by the Free Software Foundation; either 9 | version 2 of the License, or (at your option) any later version. 10 | 11 | This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 12 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 13 | PURPOSE. See the GNU General Public License for more details. 14 | 15 | A copy of the GNU General Public License is available on the World Wide Web at 16 | . You can also obtain it by writing to the Free 17 | Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA. 18 | } 19 | 20 | 21 | {$mode objfpc}{$H+} 22 | {$modeswitch typehelpers} 23 | {$modeswitch advancedrecords} 24 | 25 | interface 26 | 27 | uses 28 | Classes, SysUtils, uCollections, variants; 29 | 30 | type 31 | 32 | TMemberTable = specialize TDictionary; 33 | TFieldTable = TMemberTable; 34 | TConstTable = TMemberTable; 35 | TMethodTable = TMemberTable; 36 | TValueTable = TMemberTable; 37 | 38 | TMembers = record 39 | Fields: TFieldTable; 40 | Constants: TConstTable; 41 | Methods: TMethodTable; 42 | Values: TValueTable; 43 | constructor Create(AFields: TFieldTable; AConstants: TConstTable; 44 | AMethods: TMethodTable; AValues: TValueTable); 45 | procedure Init; 46 | end; 47 | 48 | implementation 49 | 50 | { TMembers } 51 | 52 | constructor TMembers.Create(AFields: TFieldTable; AConstants: TConstTable; 53 | AMethods: TMethodTable; AValues: TValueTable); 54 | begin 55 | Fields := AFields; 56 | Constants := AConstants; 57 | Methods := AMethods; 58 | Values := AValues; 59 | end; 60 | 61 | procedure TMembers.Init; 62 | begin 63 | Self.Fields := TFieldTable.Create; 64 | Self.Constants := TConstTable.Create; 65 | Self.Methods := TMethodTable.Create; 66 | Self.Values := TValueTable.Create; 67 | end; 68 | 69 | end. 70 | 71 | -------------------------------------------------------------------------------- /interpreter/uVariantSupport.pas: -------------------------------------------------------------------------------- 1 | unit uVariantSupport; 2 | 3 | {$mode objfpc}{$H+} 4 | {$modeswitch typehelpers} 5 | 6 | interface 7 | 8 | uses 9 | Classes, SysUtils, Variants; 10 | 11 | type 12 | 13 | TVariantHelper = type helper for Variant 14 | function toString: string; 15 | end; 16 | 17 | function VarSupportsIntf(Value: Variant; Intf: array of TGUID): Boolean; 18 | 19 | implementation 20 | 21 | function TVariantHelper.toString: string; 22 | begin 23 | if VarSupports(Self, IUnknown) then 24 | Result := (IUnknown(Self) as TInterfacedObject).toString 25 | else 26 | Result := VarToStrDef(Self, 'Null'); 27 | end; 28 | 29 | function VarSupportsIntf(Value: Variant; Intf: array of TGUID): Boolean; 30 | var 31 | i: Integer; 32 | begin 33 | Result := False; 34 | for i := 0 to High(Intf) do 35 | if VarSupports(Value, Intf[i]) then 36 | Exit(True); 37 | end; 38 | 39 | end. 40 | 41 | -------------------------------------------------------------------------------- /interpreter/ucallable.pas: -------------------------------------------------------------------------------- 1 | unit uCallable; 2 | 3 | {$mode objfpc}{$H+} 4 | 5 | interface 6 | 7 | uses 8 | Classes, SysUtils, Generics.Collections, uInterpreter, uAST, uToken; 9 | 10 | type 11 | TCallArg = class 12 | Value: Variant; 13 | Ident: TIdent; 14 | Token: TToken; 15 | constructor Create(AValue: Variant; AIdent: TIdent; AToken: TToken); 16 | end; 17 | 18 | TArgList = specialize TObjectList; 19 | 20 | ICallable = interface 21 | ['{4E512927-63FA-6E3B-0312-B27878C144EB}'] 22 | function Call(Token: TToken; Interpreter: TInterpreter; ArgList: TArgList): Variant; 23 | function toString: String; 24 | end; 25 | 26 | IValuable = interface(ICallable) 27 | ['{047FA5CB-C090-11B2-5FDB-5E3EA6245717}'] 28 | end; 29 | 30 | implementation 31 | 32 | constructor TCallArg.Create(AValue: Variant; AIdent: TIdent; AToken: TToken); 33 | begin 34 | Value := AValue; 35 | Ident := AIdent; 36 | Token := AToken; 37 | end; 38 | 39 | end. 40 | 41 | -------------------------------------------------------------------------------- /interpreter/uclassintf.pas: -------------------------------------------------------------------------------- 1 | unit uClassIntf; 2 | 3 | {$mode objfpc}{$H+} 4 | 5 | interface 6 | 7 | uses 8 | Classes, SysUtils, uCallable, uAST, uMembers; 9 | 10 | type 11 | 12 | IClassable = interface(ICallable) 13 | ['{1A8EC89F-5203-7091-61FA-ED5058712D86}'] 14 | function GetStaticMember(Ident: TIdent): Variant; 15 | procedure ExtendWith(Members: TMembers); 16 | function getName: String; 17 | property Name: String read getName; 18 | end; 19 | 20 | IGearInstance = Interface 21 | ['{9DE49CA1-F5DF-4F52-244C-604A29E52659}'] 22 | function toString: String; 23 | function GetMember(Ident: TIdent): Variant; 24 | procedure SetField(Ident: TIdent; Value: Variant); 25 | function isConstant(Ident: TIdent): Boolean; 26 | function getClassName: String; 27 | property ClassName: String read getClassName; 28 | function getMethod(const Name: String): Variant; 29 | end; 30 | 31 | ITraitable = interface 32 | ['{B0CE851D-2ECF-7FD8-C6CE-AF0CCA7533A9}'] 33 | function getIdent: TIdent; 34 | function getMethods: TMethodTable; 35 | property Ident: TIdent read getIdent; 36 | property Methods: TMethodTable read getMethods; 37 | end; 38 | 39 | 40 | implementation 41 | 42 | end. 43 | 44 | -------------------------------------------------------------------------------- /interpreter/uenumintf.pas: -------------------------------------------------------------------------------- 1 | unit uEnumIntf; 2 | 3 | {$mode objfpc}{$H+} 4 | 5 | interface 6 | 7 | uses 8 | Classes, SysUtils, uAST, Variants, uMembers, Generics.Collections, uToken, uArrayIntf; 9 | 10 | type 11 | 12 | IEnumable = Interface 13 | ['{45644E35-4C74-AB4C-25EF-BF65930F7911}'] 14 | procedure ExtendWith(Members: TMembers); 15 | function isCase(Name: String): Boolean; 16 | function ElementList: IArrayInstance; 17 | end; 18 | 19 | IEnumInstance = Interface 20 | ['{B51D4D8B-73F7-CD1B-8D70-A98E1C86910D}'] 21 | function GetMember(Ident: TIdent): Variant; 22 | function EnumName: String; 23 | function ElemName: String; 24 | function ElemValue: Variant; 25 | function ElemSetName: String; 26 | end; 27 | 28 | implementation 29 | 30 | end. 31 | 32 | -------------------------------------------------------------------------------- /interpreter/ufunc.pas: -------------------------------------------------------------------------------- 1 | unit uFunc; 2 | 3 | {$mode objfpc}{$H+} 4 | 5 | // This code is based on the online book 'Crafting Interpreters', 6 | // written by Bob Nystrom. http://craftinginterpreters.com 7 | // The code is originally written in Java. 8 | 9 | interface 10 | 11 | uses 12 | Classes, SysUtils, uCallable, uInterpreter, uAst, uMemory, uError, uToken; 13 | 14 | type 15 | 16 | TFunc = class(TInterfacedObject, ICallable) 17 | private 18 | FFuncDecl: TFuncDecl; 19 | FClosure: TMemorySpace; 20 | procedure CheckIdents(Token: TToken; IdentCalled, IdentDefined: TIdent); 21 | public 22 | property FuncDecl: TFuncDecl read FFuncDecl; 23 | constructor Create(AFuncDecl: TFuncDecl; AClosure: TMemorySpace); 24 | function Call(Token: TToken; Interpreter: TInterpreter; 25 | ArgList: TArgList): Variant; 26 | function toString: String; override; 27 | function Bind(Instance: Variant): Variant; 28 | class procedure CheckArity(Token: TToken; NumArgs, NumParams: Integer); static; 29 | end; 30 | 31 | TVal = class(TFunc, IValuable) 32 | // this is empty 33 | end; 34 | 35 | implementation 36 | 37 | const 38 | ErrInvalidNumberOfArgs = 'Invalid number of arguments. Expected %d arguments.'; 39 | ErrExpectedNoExtId = 'Did not expect external identifier "%s:".'; 40 | ErrExpectedExtId = 'Expected external identifier: "%s:".'; 41 | ErrExtIdMismatch = 'External identifier mismatch: expected "%s:".'; 42 | 43 | { TFunc } 44 | 45 | constructor TFunc.Create(AFuncDecl: TFuncDecl; AClosure: TMemorySpace); 46 | begin 47 | FFuncDecl := AFuncDecl; 48 | FClosure := AClosure; 49 | end; 50 | 51 | function TFunc.Call(Token: TToken; Interpreter: TInterpreter; 52 | ArgList: TArgList): Variant; 53 | var 54 | FuncSpace: TMemorySpace; 55 | i: Integer; 56 | begin 57 | CheckArity(Token, ArgList.Count, FFuncDecl.Params.Count); 58 | Result := Null; 59 | FuncSpace := TMemorySpace.Create(FClosure); 60 | for i := 0 to FFuncDecl.Params.Count-1 do begin 61 | CheckIdents(ArgList[i].Token, ArgList[i].Ident, FFuncDecl.Params[i].ExtIdent); 62 | FuncSpace.Store(FFuncDecl.Params[i].Ident, ArgList[i].Value); 63 | end; 64 | try 65 | Interpreter.Execute(FFuncDecl.Body, FuncSpace); 66 | except 67 | On E: EReturnFromFunc do 68 | Result := E.Value; 69 | end; 70 | end; 71 | 72 | function TFunc.toString: String; 73 | begin 74 | Result := ''; 75 | end; 76 | 77 | class procedure TFunc.CheckArity(Token: TToken; NumArgs, NumParams: Integer); 78 | begin 79 | if NumArgs <> NumParams then 80 | Raise ERuntimeError.Create(Token, Format( 81 | 'Invalid number of arguments. Expected %d arguments.', 82 | [NumParams])); 83 | end; 84 | 85 | procedure TFunc.CheckIdents(Token: TToken; IdentCalled, IdentDefined: TIdent); 86 | begin 87 | if (IdentCalled = Nil) and (IdentDefined = Nil) then Exit; 88 | if IdentDefined = Nil then 89 | Raise ERuntimeError.Create(Token, Format( 90 | ErrExpectedNoExtId, [IdentCalled.Text])); 91 | if IdentCalled = Nil then 92 | Raise ERuntimeError.Create(Token, Format( 93 | ErrExpectedExtId, [IdentDefined.Text])); 94 | if IdentCalled.Text <> IdentDefined.Text then 95 | Raise ERuntimeError.Create(Token, Format( 96 | ErrExtIdMismatch, [IdentDefined.Text])); 97 | end; 98 | 99 | function TFunc.Bind(Instance: Variant): Variant; 100 | var 101 | MemorySpace: TMemorySpace; 102 | begin 103 | MemorySpace := TMemorySpace.Create(FClosure); 104 | MemorySpace.Store('self', Instance, FFuncDecl.Token); 105 | Result := ICallable(TFunc.Create(FuncDecl, MemorySpace)); 106 | end; 107 | 108 | end. 109 | 110 | -------------------------------------------------------------------------------- /interpreter/uhash.pas: -------------------------------------------------------------------------------- 1 | unit uHash; 2 | 3 | {$mode objfpc}{$H+} 4 | 5 | interface 6 | 7 | uses 8 | Classes, SysUtils; 9 | 10 | const 11 | k_hash = 613; 12 | N_hash = 1008; //size of hash table (1009 = prime number) 13 | 14 | 15 | function MakeHash(const Ident: string):LongInt; 16 | 17 | implementation 18 | 19 | function MakeHash(const Ident: string):LongInt; 20 | var 21 | i, h, l: Cardinal; 22 | begin 23 | h := 0; 24 | l := Length(Ident); 25 | for i := 1 to l do 26 | h := k_hash * h + Ord(Ident[i]); 27 | Result := ((h shl 2) shr 2) Mod N_hash; //least significant 30 bits 28 | end; 29 | 30 | end. 31 | 32 | -------------------------------------------------------------------------------- /interpreter/umembers.pas: -------------------------------------------------------------------------------- 1 | unit uMembers; 2 | 3 | {$mode objfpc}{$H+} 4 | {$modeswitch typehelpers} 5 | {$modeswitch advancedrecords} 6 | 7 | interface 8 | 9 | uses 10 | Classes, SysUtils, Generics.Collections, variants; 11 | 12 | type 13 | 14 | TMemberTable = specialize TDictionary; 15 | TFieldTable = TMemberTable; 16 | TConstTable = TMemberTable; 17 | TMethodTable = TMemberTable; 18 | TValueTable = TMemberTable; 19 | 20 | TMembers = record 21 | Fields: TFieldTable; 22 | Constants: TConstTable; 23 | Methods: TMethodTable; 24 | Values: TValueTable; 25 | constructor Create(AFields: TFieldTable; AConstants: TConstTable; 26 | AValues: TValueTable; AMethods: TMethodTable); 27 | procedure Init; 28 | end; 29 | 30 | implementation 31 | 32 | { TMembers } 33 | 34 | constructor TMembers.Create(AFields: TFieldTable; AConstants: TConstTable; 35 | AValues: TValueTable; AMethods: TMethodTable); 36 | begin 37 | Fields := AFields; 38 | Constants := AConstants; 39 | Methods := AMethods; 40 | Values := AValues; 41 | end; 42 | 43 | procedure TMembers.Init; 44 | begin 45 | Self.Fields := TFieldTable.Create; 46 | Self.Constants := TConstTable.Create; 47 | Self.Methods := TMethodTable.Create; 48 | Self.Values := TValueTable.Create; 49 | end; 50 | 51 | end. 52 | 53 | -------------------------------------------------------------------------------- /interpreter/ureader.pas: -------------------------------------------------------------------------------- 1 | unit uReader; 2 | 3 | { This unit contains the reader class that reads a file and provides characters 4 | to the Lexer. 5 | 6 | Copyright (C) 2018 J. de Haan jdehaan2014@gmail.com 7 | 8 | This source is free software; you can redistribute it and/or modify it under the terms 9 | of the GNU General Public License as published by the Free Software Foundation; either 10 | version 2 of the License, or (at your option) any later version. 11 | 12 | This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 13 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 14 | PURPOSE. See the GNU General Public License for more details. 15 | 16 | A copy of the GNU General Public License is available on the World Wide Web at 17 | . You can also obtain it by writing to the Free 18 | Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA. 19 | } 20 | 21 | {$mode objfpc}{$H+} 22 | 23 | interface 24 | 25 | uses 26 | Classes, SysUtils, Generics.Collections; 27 | 28 | const 29 | //on Unix '^D' on windows ^Z (#26) 30 | {$IFDEF UNIX} 31 | FileEnding = ^D; 32 | {$ENDIF} 33 | {$IFDEF WINDOWS} 34 | FileEnding = ^Z //(#26) 35 | {$ENDIF} 36 | 37 | type 38 | 39 | TInputType = (itPrompt, itFile); 40 | 41 | { TReader } 42 | 43 | TReader = class(TStringList) 44 | private 45 | FFileName: TFileName; 46 | FFileIndex: Integer; 47 | Index: LongInt; 48 | function getPeekChar: char; 49 | public 50 | property FileName: TFileName read FFileName; 51 | property FileIndex: Integer read FFileIndex; 52 | property PeekChar: char read getPeekChar; 53 | constructor Create(Source: String; InputType: TInputType); 54 | function NextChar: char; 55 | end; 56 | 57 | TFileNameArray = specialize TList; 58 | 59 | var 60 | FileNameArray: TFileNameArray; 61 | 62 | implementation 63 | 64 | { TReader } 65 | 66 | function TReader.getPeekChar: char; //peek at next character, but don't process it 67 | begin 68 | try 69 | Result := Text[Index]; 70 | except 71 | Result := FileEnding; 72 | end; 73 | end; 74 | 75 | constructor TReader.Create(Source: String; InputType: TInputType); 76 | begin 77 | inherited Create; 78 | FFileName := ''; 79 | FFileIndex := -1; 80 | Index := 1; 81 | case InputType of 82 | itPrompt: add(Source); 83 | itFile: 84 | begin 85 | FFileName := Source; 86 | FFileIndex := FileNameArray.Add(FFileName); 87 | LoadFromFile(FFileName); 88 | end; 89 | end; 90 | end; 91 | 92 | function TReader.NextChar: char; 93 | begin 94 | try 95 | Result := Text[Index]; 96 | Inc(Index); 97 | except 98 | Result := FileEnding; 99 | end; 100 | end; 101 | 102 | initialization 103 | FileNameArray := TFileNameArray.Create; 104 | finalization 105 | FileNameArray.Free; 106 | 107 | end. 108 | 109 | -------------------------------------------------------------------------------- /interpreter/ustandardcrt.pas: -------------------------------------------------------------------------------- 1 | unit uStandardCRT; 2 | 3 | {$mode objfpc}{$H+} 4 | 5 | interface 6 | 7 | uses 8 | Classes, SysUtils, uInterpreter, uCallable, uToken, Variants, uMemory; 9 | 10 | type 11 | 12 | TClrScr = class(TInterfacedObject, ICallable) 13 | function Call(Token: TToken; Interpreter: TInterpreter; ArgList: TArgList): Variant; 14 | end; 15 | 16 | TWindow = class(TInterfacedObject, ICallable) 17 | function Call(Token: TToken; Interpreter: TInterpreter; ArgList: TArgList): Variant; 18 | end; 19 | 20 | TGotoXY = class(TInterfacedObject, ICallable) 21 | function Call(Token: TToken; Interpreter: TInterpreter; ArgList: TArgList): Variant; 22 | end; 23 | 24 | 25 | procedure StoreStandardCRTFunctions(GlobalSpace: TMemorySpace); 26 | 27 | 28 | implementation 29 | uses uFunc, CRT; 30 | 31 | { TWindow } 32 | 33 | function TWindow.Call(Token: TToken; Interpreter: TInterpreter; 34 | ArgList: TArgList): Variant; 35 | var 36 | x1,y1,x2,y2: Byte; 37 | begin 38 | TFunc.CheckArity(Token, ArgList.Count, 4); 39 | x1 := Byte(ArgList[0].Value); 40 | y1 := Byte(ArgList[1].Value); 41 | x2 := Byte(ArgList[2].Value); 42 | y2 := Byte(ArgList[3].Value); 43 | 44 | Result := Null; 45 | Window(x1,y1,x2,y2); 46 | end; 47 | 48 | { TClrScr } 49 | 50 | function TClrScr.Call(Token: TToken; Interpreter: TInterpreter; 51 | ArgList: TArgList): Variant; 52 | begin 53 | TFunc.CheckArity(Token, ArgList.Count, 0); 54 | Result := Null; 55 | ClrScr; 56 | end; 57 | 58 | { TGotoXY } 59 | 60 | function TGotoXY.Call(Token: TToken; Interpreter: TInterpreter; 61 | ArgList: TArgList): Variant; 62 | var 63 | x,y: Byte; 64 | begin 65 | TFunc.CheckArity(Token, ArgList.Count, 2); 66 | x := Byte(ArgList[0].Value); 67 | y := Byte(ArgList[1].Value); 68 | 69 | Result := Null; 70 | GotoXY(x,y); 71 | end; 72 | 73 | 74 | 75 | procedure StoreStandardCRTFunctions(GlobalSpace: TMemorySpace); 76 | var 77 | Token: TToken; 78 | begin 79 | Token := TToken.Create(ttIdentifier, '', Null, 0, 0); 80 | GlobalSpace.Store('window', ICallable(TWindow.Create), Token); 81 | GlobalSpace.Store('gotoXY', ICallable(TGotoXY.Create), Token); 82 | GlobalSpace.Store('clrScr', ICallable(TClrScr.Create), Token); 83 | end; 84 | 85 | end. 86 | 87 | -------------------------------------------------------------------------------- /interpreter/utils_.pas: -------------------------------------------------------------------------------- 1 | unit utils; 2 | 3 | {$mode objfpc}{$H+} 4 | 5 | interface 6 | 7 | function IPlusPlus(var i: Integer): Integer; 8 | function PlusPlusI(var i: Integer): Integer; 9 | 10 | function IMinMin(var i: Integer): Integer; 11 | function MinMinI(var i: Integer): Integer; 12 | 13 | implementation 14 | 15 | function IPlusPlus(var i: Integer): Integer; 16 | begin 17 | Result := i; 18 | Inc(i); 19 | end; 20 | 21 | function PlusPlusI(var i: Integer): Integer; 22 | begin 23 | Inc(i); 24 | Result := i; 25 | end; 26 | 27 | function IMinMin(var i: Integer): Integer; 28 | begin 29 | Result := i; 30 | Dec(i); 31 | end; 32 | 33 | function MinMinI(var i: Integer): Integer; 34 | begin 35 | Dec(i); 36 | Result := i; 37 | end; 38 | 39 | end. 40 | 41 | -------------------------------------------------------------------------------- /interpreter/utuple.pas: -------------------------------------------------------------------------------- 1 | unit uTuple; 2 | 3 | {$mode objfpc}{$H+} 4 | 5 | interface 6 | 7 | uses 8 | Classes, SysUtils, uTupleIntf, uToken; 9 | 10 | type 11 | 12 | TTuple = class(TInterfacedObject, ITuple) 13 | private 14 | FElements: TTupleElements; 15 | function getElements: TTupleElements; 16 | public 17 | property Elements: TTupleElements read getElements; 18 | constructor Create; 19 | destructor Destroy; override; 20 | function toString: String; override; 21 | function Get(i: Integer; Token: TToken): Variant; 22 | procedure Put(i: Integer; Value: Variant; Token: TToken); 23 | end; 24 | 25 | implementation 26 | uses Variants, uVariantSupport, uError; 27 | 28 | { TTuple } 29 | 30 | function TTuple.getElements: TTupleElements; 31 | begin 32 | Result := FElements 33 | end; 34 | 35 | constructor TTuple.Create; 36 | begin 37 | FElements := TTupleElements.Create; 38 | end; 39 | 40 | destructor TTuple.Destroy; 41 | begin 42 | FElements.Free; 43 | inherited Destroy; 44 | end; 45 | 46 | function TTuple.toString: String; 47 | var 48 | i: Integer; 49 | 50 | function getStr(Value: Variant): String; 51 | begin 52 | Result := Value.toString; 53 | if VarType(Value) = varString then 54 | Result := QuotedStr(Result); 55 | end; 56 | 57 | begin 58 | Result := '('; 59 | if FElements.Count > 0 then begin 60 | for i := 0 to FElements.Count-2 do 61 | Result += getStr(FElements[i]) + ', '; 62 | Result += getStr(FElements[FElements.Count-1]); 63 | end; 64 | Result += ')'; 65 | end; 66 | 67 | function TTuple.Get(i: Integer; Token: TToken): Variant; 68 | var 69 | Index, Count: Integer; 70 | begin 71 | Index := i-1; // A tuple starts at 1, but FElements starts at 0 72 | Count := FElements.Count; 73 | if Count = 0 then 74 | Result := Unassigned 75 | else if (Index >= 0) and (Index < Count) then 76 | Result := FElements[Index] 77 | else 78 | Raise ERuntimeError.Create(Token, 79 | 'Index ('+ IntToStr(i) + ') out of range ('+ '1,' + IntToStr(Count) + ').'); 80 | end; 81 | 82 | procedure TTuple.Put(i: Integer; Value: Variant; Token: TToken); 83 | var 84 | Index, Count: Integer; 85 | begin 86 | Index := i-1; // A tuple starts at 1, but FElements starts at 0 87 | Count := FElements.Count; 88 | if (Index >= 0) and (Index < Count) then 89 | FElements[Index] := Value 90 | else 91 | Raise ERuntimeError.Create(Token, 92 | 'Index ('+ IntToStr(i) + ') out of range ('+ '1,' + IntToStr(Count) + ').'); 93 | end; 94 | 95 | end. 96 | 97 | -------------------------------------------------------------------------------- /interpreter/utupleintf.pas: -------------------------------------------------------------------------------- 1 | unit uTupleIntf; 2 | 3 | {$mode objfpc}{$H+} 4 | 5 | interface 6 | 7 | uses 8 | Classes, SysUtils, Generics.Collections, uToken; 9 | 10 | type 11 | 12 | TTupleElements = specialize TList; 13 | 14 | ITuple = interface 15 | ['{D30402C8-77E2-88D5-21A1-7CCB1CA12D9B}'] 16 | function getElements: TTupleElements; 17 | property Elements: TTupleElements read getElements; 18 | function Get(i: Integer; Token: TToken): Variant; 19 | procedure Put(i: Integer; Value: Variant; Token: TToken); 20 | function toString: String; 21 | end; 22 | 23 | implementation 24 | 25 | end. 26 | 27 | -------------------------------------------------------------------------------- /interpreter/uvisitor.pas: -------------------------------------------------------------------------------- 1 | unit uVisitor; 2 | 3 | { This unit contains the base and parent class of the visitor. Each visitor class 4 | inherits from this basic TVisitor class. 5 | 6 | Copyright (C) 2018 J. de Haan jdehaan2014@gmail.com 7 | 8 | This source is free software; you can redistribute it and/or modify it under the terms 9 | of the GNU General Public License as published by the Free Software Foundation; either 10 | version 2 of the License, or (at your option) any later version. 11 | 12 | This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 13 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 14 | PURPOSE. See the GNU General Public License for more details. 15 | 16 | A copy of the GNU General Public License is available on the World Wide Web at 17 | . You can also obtain it by writing to the Free 18 | Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA. 19 | } 20 | 21 | {$mode objfpc}{$H+} 22 | 23 | interface 24 | 25 | uses 26 | Classes, SysUtils, typinfo; 27 | 28 | type 29 | 30 | {$M+} 31 | 32 | TVisitor = class 33 | published 34 | function VisitFunc(Node: TObject): Variant; virtual; 35 | procedure VisitProc(Node: TObject); virtual; 36 | end; 37 | 38 | implementation 39 | 40 | type 41 | TVisitFunc = function(Node: TObject): Variant of object; 42 | TVisitProc = procedure(Node: TObject) of object; 43 | 44 | function TVisitor.VisitFunc(Node: TObject): Variant; 45 | var 46 | VisitName: shortstring; 47 | VisitMethod: TMethod; 48 | doVisit: TVisitFunc; 49 | SelfName: string = ''; 50 | begin 51 | // Build visitor name: e.g. VisitBinaryExpr from 'Visit' and TBinaryExpr 52 | VisitName := 'Visit' + Copy(Node.ClassName, 2, 255); // remove 'T' 53 | SelfName := Self.ClassName; 54 | VisitMethod.Data := Self; 55 | VisitMethod.Code := Self.MethodAddress(VisitName); 56 | if Assigned(VisitMethod.Code) then begin 57 | doVisit := TVisitFunc(VisitMethod); 58 | Result := doVisit(Node); 59 | end 60 | else 61 | Raise 62 | Exception.Create(Format('No %s.%s method found.', [SelfName, VisitName])); 63 | end; 64 | 65 | procedure TVisitor.VisitProc(Node: TObject); 66 | var 67 | VisitName: shortstring; 68 | VisitMethod: TMethod; 69 | doVisit: TVisitProc; 70 | SelfName: string = ''; 71 | begin 72 | // Build visitor name: e.g. VisitBinaryExpr from 'Visit' and TBinaryExpr 73 | VisitName := 'Visit' + Copy(Node.ClassName, 2, 255); // remove 'T' 74 | SelfName := Self.ClassName; 75 | VisitMethod.Data := Self; 76 | VisitMethod.Code := Self.MethodAddress(VisitName); 77 | if Assigned(VisitMethod.Code) then begin 78 | doVisit := TVisitProc(VisitMethod); 79 | doVisit(Node); 80 | end 81 | else 82 | Raise 83 | Exception.Create(Format('No %s.%s method found.', [SelfName, VisitName])); 84 | end; 85 | 86 | end. 87 | 88 | 89 | --------------------------------------------------------------------------------