├── tests ├── fuzz_input │ ├── 000.wl │ ├── 001.wl │ ├── 002.wl │ ├── 003.wl │ ├── 004.wl │ ├── 007.wl │ ├── 008.wl │ ├── 009.wl │ ├── 010.wl │ ├── 011.wl │ ├── 012.wl │ ├── 017.wl │ ├── 021.wl │ ├── 024.wl │ ├── 025.wl │ ├── 026.wl │ ├── 027.wl │ ├── 028.wl │ ├── 029.wl │ ├── 030.wl │ ├── 031.wl │ ├── 038.wl │ ├── 039.wl │ ├── 040.wl │ ├── 041.wl │ ├── 042.wl │ ├── 043.wl │ ├── 044.wl │ ├── 045.wl │ ├── 046.wl │ ├── 047.wl │ ├── 048.wl │ ├── 049.wl │ ├── 055.wl │ ├── 057.wl │ ├── 058.wl │ ├── 059.wl │ ├── 060.wl │ ├── 061.wl │ ├── 062.wl │ ├── 063.wl │ ├── 064.wl │ ├── 013.wl │ ├── 014.wl │ ├── 015.wl │ ├── 016.wl │ ├── 018.wl │ ├── 020.wl │ ├── 022.wl │ ├── 023.wl │ ├── 032.wl │ ├── 033.wl │ ├── 034.wl │ ├── 035.wl │ ├── 036.wl │ ├── 037.wl │ ├── 050.wl │ ├── 052.wl │ ├── 053.wl │ ├── 056.wl │ ├── 005.wl │ ├── 006.wl │ ├── 019.wl │ ├── 051.wl │ ├── 065.wl │ ├── 067.wl │ ├── 068.wl │ ├── 069.wl │ ├── 054.wl │ ├── 070.wl │ ├── 071.wl │ ├── 072.wl │ ├── 073.wl │ ├── 074.wl │ ├── 075.wl │ ├── 109.wl │ ├── 066.wl │ ├── 085.wl │ ├── 086.wl │ ├── 094.wl │ ├── 095.wl │ ├── 103.wl │ ├── 090.wl │ ├── 092.wl │ ├── 097.wl │ ├── 102.wl │ ├── 110.wl │ ├── 077.wl │ ├── 078.wl │ ├── 079.wl │ ├── 080.wl │ ├── 082.wl │ ├── 083.wl │ ├── 087.wl │ ├── 088.wl │ ├── 076.wl │ ├── 081.wl │ ├── 111.wl │ ├── 093.wl │ ├── 112.wl │ ├── 091.wl │ ├── 096.wl │ ├── 104.wl │ ├── 105.wl │ ├── 108.wl │ ├── 084.wl │ ├── 106.wl │ ├── 107.wl │ ├── 089.wl │ ├── 098.wl │ ├── 099.wl │ ├── 100.wl │ └── 101.wl ├── fuzz.c └── test.c ├── .gitignore ├── TODO.md ├── examples ├── loop.wl ├── procedure.wl └── procedure_2.wl ├── ide └── vscode │ └── wl-language │ ├── language-configuration.json │ ├── package.json │ ├── themes │ └── wl-theme.json │ └── syntaxes │ └── wl.tmLanguage.json ├── Makefile ├── main.c ├── wl.h ├── README.md └── LANGUAGE.md /tests/fuzz_input/000.wl: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /tests/fuzz_input/001.wl: -------------------------------------------------------------------------------- 1 | 0.4 -------------------------------------------------------------------------------- /tests/fuzz_input/002.wl: -------------------------------------------------------------------------------- 1 | none -------------------------------------------------------------------------------- /tests/fuzz_input/003.wl: -------------------------------------------------------------------------------- 1 | true -------------------------------------------------------------------------------- /tests/fuzz_input/004.wl: -------------------------------------------------------------------------------- 1 | false -------------------------------------------------------------------------------- /tests/fuzz_input/007.wl: -------------------------------------------------------------------------------- 1 | "\\" -------------------------------------------------------------------------------- /tests/fuzz_input/008.wl: -------------------------------------------------------------------------------- 1 | "\n" -------------------------------------------------------------------------------- /tests/fuzz_input/009.wl: -------------------------------------------------------------------------------- 1 | "\t" -------------------------------------------------------------------------------- /tests/fuzz_input/010.wl: -------------------------------------------------------------------------------- 1 | "\r" -------------------------------------------------------------------------------- /tests/fuzz_input/011.wl: -------------------------------------------------------------------------------- 1 | "\"" -------------------------------------------------------------------------------- /tests/fuzz_input/012.wl: -------------------------------------------------------------------------------- 1 | "\'" -------------------------------------------------------------------------------- /tests/fuzz_input/017.wl: -------------------------------------------------------------------------------- 1 | +{} -------------------------------------------------------------------------------- /tests/fuzz_input/021.wl: -------------------------------------------------------------------------------- 1 | 1+2*3 -------------------------------------------------------------------------------- /tests/fuzz_input/024.wl: -------------------------------------------------------------------------------- 1 | 1+2 -------------------------------------------------------------------------------- /tests/fuzz_input/025.wl: -------------------------------------------------------------------------------- 1 | 2-1 -------------------------------------------------------------------------------- /tests/fuzz_input/026.wl: -------------------------------------------------------------------------------- 1 | 1-2 -------------------------------------------------------------------------------- /tests/fuzz_input/027.wl: -------------------------------------------------------------------------------- 1 | 2*3 -------------------------------------------------------------------------------- /tests/fuzz_input/028.wl: -------------------------------------------------------------------------------- 1 | 2/3 -------------------------------------------------------------------------------- /tests/fuzz_input/029.wl: -------------------------------------------------------------------------------- 1 | 4/2 -------------------------------------------------------------------------------- /tests/fuzz_input/030.wl: -------------------------------------------------------------------------------- 1 | 0%2 -------------------------------------------------------------------------------- /tests/fuzz_input/031.wl: -------------------------------------------------------------------------------- 1 | 3%2 -------------------------------------------------------------------------------- /tests/fuzz_input/038.wl: -------------------------------------------------------------------------------- 1 | 1+2.0 -------------------------------------------------------------------------------- /tests/fuzz_input/039.wl: -------------------------------------------------------------------------------- 1 | 2-1.0 -------------------------------------------------------------------------------- /tests/fuzz_input/040.wl: -------------------------------------------------------------------------------- 1 | 1-2.0 -------------------------------------------------------------------------------- /tests/fuzz_input/041.wl: -------------------------------------------------------------------------------- 1 | 2*3.0 -------------------------------------------------------------------------------- /tests/fuzz_input/042.wl: -------------------------------------------------------------------------------- 1 | 2/3.0 -------------------------------------------------------------------------------- /tests/fuzz_input/043.wl: -------------------------------------------------------------------------------- 1 | 4/2.0 -------------------------------------------------------------------------------- /tests/fuzz_input/044.wl: -------------------------------------------------------------------------------- 1 | 1.0+2 -------------------------------------------------------------------------------- /tests/fuzz_input/045.wl: -------------------------------------------------------------------------------- 1 | 2.0-1 -------------------------------------------------------------------------------- /tests/fuzz_input/046.wl: -------------------------------------------------------------------------------- 1 | 1.0-2 -------------------------------------------------------------------------------- /tests/fuzz_input/047.wl: -------------------------------------------------------------------------------- 1 | 2.0*3 -------------------------------------------------------------------------------- /tests/fuzz_input/048.wl: -------------------------------------------------------------------------------- 1 | 2.0/3 -------------------------------------------------------------------------------- /tests/fuzz_input/049.wl: -------------------------------------------------------------------------------- 1 | 4.0/2 -------------------------------------------------------------------------------- /tests/fuzz_input/055.wl: -------------------------------------------------------------------------------- 1 | -12 -------------------------------------------------------------------------------- /tests/fuzz_input/057.wl: -------------------------------------------------------------------------------- 1 | 1<2 -------------------------------------------------------------------------------- /tests/fuzz_input/058.wl: -------------------------------------------------------------------------------- 1 | 2<1 -------------------------------------------------------------------------------- /tests/fuzz_input/059.wl: -------------------------------------------------------------------------------- 1 | 1>2 -------------------------------------------------------------------------------- /tests/fuzz_input/060.wl: -------------------------------------------------------------------------------- 1 | 2>1 -------------------------------------------------------------------------------- /tests/fuzz_input/061.wl: -------------------------------------------------------------------------------- 1 | 1==1 -------------------------------------------------------------------------------- /tests/fuzz_input/062.wl: -------------------------------------------------------------------------------- 1 | 1==2 -------------------------------------------------------------------------------- /tests/fuzz_input/063.wl: -------------------------------------------------------------------------------- 1 | 1!=1 -------------------------------------------------------------------------------- /tests/fuzz_input/064.wl: -------------------------------------------------------------------------------- 1 | 1!=2 -------------------------------------------------------------------------------- /tests/fuzz_input/013.wl: -------------------------------------------------------------------------------- 1 | "\xFF" -------------------------------------------------------------------------------- /tests/fuzz_input/014.wl: -------------------------------------------------------------------------------- 1 | "\x0F" -------------------------------------------------------------------------------- /tests/fuzz_input/015.wl: -------------------------------------------------------------------------------- 1 | "\xF0" -------------------------------------------------------------------------------- /tests/fuzz_input/016.wl: -------------------------------------------------------------------------------- 1 | [1, 2, 3] -------------------------------------------------------------------------------- /tests/fuzz_input/018.wl: -------------------------------------------------------------------------------- 1 | +{a:1} -------------------------------------------------------------------------------- /tests/fuzz_input/020.wl: -------------------------------------------------------------------------------- 1 | 10-1-2 -------------------------------------------------------------------------------- /tests/fuzz_input/022.wl: -------------------------------------------------------------------------------- 1 | (1+2)*3 -------------------------------------------------------------------------------- /tests/fuzz_input/023.wl: -------------------------------------------------------------------------------- 1 | 1+(2*3) -------------------------------------------------------------------------------- /tests/fuzz_input/032.wl: -------------------------------------------------------------------------------- 1 | 1.0+2.0 -------------------------------------------------------------------------------- /tests/fuzz_input/033.wl: -------------------------------------------------------------------------------- 1 | 2.0-1.0 -------------------------------------------------------------------------------- /tests/fuzz_input/034.wl: -------------------------------------------------------------------------------- 1 | 1.0-2.0 -------------------------------------------------------------------------------- /tests/fuzz_input/035.wl: -------------------------------------------------------------------------------- 1 | 2.0*3.0 -------------------------------------------------------------------------------- /tests/fuzz_input/036.wl: -------------------------------------------------------------------------------- 1 | 2.0/3.0 -------------------------------------------------------------------------------- /tests/fuzz_input/037.wl: -------------------------------------------------------------------------------- 1 | 4.0/2.0 -------------------------------------------------------------------------------- /tests/fuzz_input/050.wl: -------------------------------------------------------------------------------- 1 | len [] -------------------------------------------------------------------------------- /tests/fuzz_input/052.wl: -------------------------------------------------------------------------------- 1 | len {} -------------------------------------------------------------------------------- /tests/fuzz_input/053.wl: -------------------------------------------------------------------------------- 1 | len {a:1} -------------------------------------------------------------------------------- /tests/fuzz_input/056.wl: -------------------------------------------------------------------------------- 1 | -12.34 -------------------------------------------------------------------------------- /tests/fuzz_input/005.wl: -------------------------------------------------------------------------------- 1 | "Hello, world!" -------------------------------------------------------------------------------- /tests/fuzz_input/006.wl: -------------------------------------------------------------------------------- 1 | 'Hello, world!' -------------------------------------------------------------------------------- /tests/fuzz_input/019.wl: -------------------------------------------------------------------------------- 1 | +{a:1,b:2,c:3} -------------------------------------------------------------------------------- /tests/fuzz_input/051.wl: -------------------------------------------------------------------------------- 1 | len [1, 2, 3] -------------------------------------------------------------------------------- /tests/fuzz_input/065.wl: -------------------------------------------------------------------------------- 1 | let a = 1 2 | a -------------------------------------------------------------------------------- /tests/fuzz_input/067.wl: -------------------------------------------------------------------------------- 1 | [5, 6, 7][0] -------------------------------------------------------------------------------- /tests/fuzz_input/068.wl: -------------------------------------------------------------------------------- 1 | [5, 6, 7][1] -------------------------------------------------------------------------------- /tests/fuzz_input/069.wl: -------------------------------------------------------------------------------- 1 | [5, 6, 7][2] -------------------------------------------------------------------------------- /tests/fuzz_input/054.wl: -------------------------------------------------------------------------------- 1 | len {a:1,b:2,c:3} -------------------------------------------------------------------------------- /tests/fuzz_input/070.wl: -------------------------------------------------------------------------------- 1 | +{a:5,b:6,c:7}.a -------------------------------------------------------------------------------- /tests/fuzz_input/071.wl: -------------------------------------------------------------------------------- 1 | +{a:5,b:6,c:7}.b -------------------------------------------------------------------------------- /tests/fuzz_input/072.wl: -------------------------------------------------------------------------------- 1 | +{a:5,b:6,c:7}.c -------------------------------------------------------------------------------- /tests/fuzz_input/073.wl: -------------------------------------------------------------------------------- 1 | +{a:5,b:6,c:7}['a'] -------------------------------------------------------------------------------- /tests/fuzz_input/074.wl: -------------------------------------------------------------------------------- 1 | +{a:5,b:6,c:7}['b'] -------------------------------------------------------------------------------- /tests/fuzz_input/075.wl: -------------------------------------------------------------------------------- 1 | +{a:5,b:6,c:7}['c'] -------------------------------------------------------------------------------- /tests/fuzz_input/109.wl: -------------------------------------------------------------------------------- 1 | Hello, world! -------------------------------------------------------------------------------- /tests/fuzz_input/066.wl: -------------------------------------------------------------------------------- 1 | let a = 1 2 | a = 2 3 | a -------------------------------------------------------------------------------- /tests/fuzz_input/085.wl: -------------------------------------------------------------------------------- 1 | if 1 < 2: 2 | 1 3 | 2 -------------------------------------------------------------------------------- /tests/fuzz_input/086.wl: -------------------------------------------------------------------------------- 1 | if 1 > 2: 2 | 1 3 | 2 -------------------------------------------------------------------------------- /tests/fuzz_input/094.wl: -------------------------------------------------------------------------------- 1 | procedure P() 2 | 0 -------------------------------------------------------------------------------- /tests/fuzz_input/095.wl: -------------------------------------------------------------------------------- 1 | procedure P(a) 2 | a -------------------------------------------------------------------------------- /tests/fuzz_input/103.wl: -------------------------------------------------------------------------------- 1 | P() 2 | procedure P() 1 -------------------------------------------------------------------------------- /tests/fuzz_input/090.wl: -------------------------------------------------------------------------------- 1 | for a in ['A', 'B', 'C']: 2 | a -------------------------------------------------------------------------------- /tests/fuzz_input/092.wl: -------------------------------------------------------------------------------- 1 | for a in {x:1,y:2,z:3}: 2 | a -------------------------------------------------------------------------------- /tests/fuzz_input/097.wl: -------------------------------------------------------------------------------- 1 | procedure P() 2 | 0 3 | P() -------------------------------------------------------------------------------- /tests/fuzz_input/102.wl: -------------------------------------------------------------------------------- 1 | procedure N(n) n 2 | N(1) + N(2) -------------------------------------------------------------------------------- /tests/fuzz_input/110.wl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/fuzz_input/077.wl: -------------------------------------------------------------------------------- 1 | let x = {a:5,b:6,c:7} 2 | x.a = true 3 | x -------------------------------------------------------------------------------- /tests/fuzz_input/078.wl: -------------------------------------------------------------------------------- 1 | let x = {a:5,b:6,c:7} 2 | x.b = true 3 | x -------------------------------------------------------------------------------- /tests/fuzz_input/079.wl: -------------------------------------------------------------------------------- 1 | let x = {a:5,b:6,c:7} 2 | x.c = true 3 | x -------------------------------------------------------------------------------- /tests/fuzz_input/080.wl: -------------------------------------------------------------------------------- 1 | let x = {a:5,b:6,c:7} 2 | x['a'] = true 3 | x -------------------------------------------------------------------------------- /tests/fuzz_input/082.wl: -------------------------------------------------------------------------------- 1 | let x = {a:5,b:6,c:7} 2 | x['c'] = true 3 | x -------------------------------------------------------------------------------- /tests/fuzz_input/083.wl: -------------------------------------------------------------------------------- 1 | let a 2 | let b 3 | let c 4 | a = b = c = 5 -------------------------------------------------------------------------------- /tests/fuzz_input/087.wl: -------------------------------------------------------------------------------- 1 | if 1 < 2: 2 | 1 3 | else 4 | 2 5 | 3 -------------------------------------------------------------------------------- /tests/fuzz_input/088.wl: -------------------------------------------------------------------------------- 1 | if 1 > 2: 2 | 1 3 | else 4 | 2 5 | 3 -------------------------------------------------------------------------------- /tests/fuzz_input/076.wl: -------------------------------------------------------------------------------- 1 | let x = 1 2 | { 3 | let x = 2 4 | x 5 | } -------------------------------------------------------------------------------- /tests/fuzz_input/081.wl: -------------------------------------------------------------------------------- 1 | let x = {a:5,b:6,c:7} 2 | x['b'] = true 3 | x 4 | -------------------------------------------------------------------------------- /tests/fuzz_input/111.wl: -------------------------------------------------------------------------------- 1 | let a = -------------------------------------------------------------------------------- /tests/fuzz_input/093.wl: -------------------------------------------------------------------------------- 1 | for a, b in {x:1,y:2,z:3}: { 2 | a 3 | b 4 | } -------------------------------------------------------------------------------- /tests/fuzz_input/112.wl: -------------------------------------------------------------------------------- 1 | let a = 2 | a -------------------------------------------------------------------------------- /tests/fuzz_input/091.wl: -------------------------------------------------------------------------------- 1 | for a, b in ['A', 'B', 'C']: { 2 | a 3 | b 4 | } -------------------------------------------------------------------------------- /tests/fuzz_input/096.wl: -------------------------------------------------------------------------------- 1 | procedure P(a, b, c) { 2 | a 3 | b 4 | c 5 | } -------------------------------------------------------------------------------- /tests/fuzz_input/104.wl: -------------------------------------------------------------------------------- 1 | P() 2 | procedure P() 1 3 | { 4 | procedure P() 2 5 | } -------------------------------------------------------------------------------- /tests/fuzz_input/105.wl: -------------------------------------------------------------------------------- 1 | procedure P() 1 2 | P() 3 | { 4 | procedure P() 2 5 | } -------------------------------------------------------------------------------- /tests/fuzz_input/108.wl: -------------------------------------------------------------------------------- 1 | procedure P() 1 2 | { 3 | procedure P() 2 4 | } 5 | P() -------------------------------------------------------------------------------- /tests/fuzz_input/084.wl: -------------------------------------------------------------------------------- 1 | let a 2 | let b 3 | let c 4 | a = b = c = 5 5 | a 6 | b 7 | c -------------------------------------------------------------------------------- /tests/fuzz_input/106.wl: -------------------------------------------------------------------------------- 1 | procedure P() 1 2 | { 3 | P() 4 | procedure P() 2 5 | } -------------------------------------------------------------------------------- /tests/fuzz_input/107.wl: -------------------------------------------------------------------------------- 1 | procedure P() 1 2 | { 3 | procedure P() 2 4 | P() 5 | } -------------------------------------------------------------------------------- /tests/fuzz_input/089.wl: -------------------------------------------------------------------------------- 1 | let i = 0 2 | while i < 3: { 3 | true 4 | i = i + 1 5 | } 6 | -------------------------------------------------------------------------------- /tests/fuzz_input/098.wl: -------------------------------------------------------------------------------- 1 | procedure P(a, b, c) { 2 | a 3 | b 4 | c 5 | } 6 | P() -------------------------------------------------------------------------------- /tests/fuzz_input/099.wl: -------------------------------------------------------------------------------- 1 | procedure P(a, b, c) { 2 | a 3 | b 4 | c 5 | } 6 | P(1) -------------------------------------------------------------------------------- /tests/fuzz_input/100.wl: -------------------------------------------------------------------------------- 1 | procedure P(a, b, c) { 2 | a 3 | b 4 | c 5 | } 6 | P(1, 2) -------------------------------------------------------------------------------- /tests/fuzz_input/101.wl: -------------------------------------------------------------------------------- 1 | procedure P(a, b, c) { 2 | a 3 | b 4 | c 5 | } 6 | P(1, 2, 3) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | a.out 2 | coverage_html/ 3 | test 4 | test.exe 5 | test_cov 6 | fuzz 7 | wl 8 | wl.exe 9 | wl_cov -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | * Don't allow [] selections to go over newlines 2 | * Make sure maps and arrays can't be keys of a map 3 | * Decide and document how comments work 4 | * Improve the formatting of the output 5 | -------------------------------------------------------------------------------- /examples/loop.wl: -------------------------------------------------------------------------------- 1 | let items = ['Apple', 'Orange', 'Strawberry'] 2 | 3 | let list = 4 | 8 | 9 | 10 | 11 | Fruit List 12 | 13 | 14 | My list: 15 | \{list} 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/procedure.wl: -------------------------------------------------------------------------------- 1 | 2 | procedure my_page_template(title, content) { 3 | 4 | 5 | \{escape title} 6 | 7 | 8 | \{content} 9 | 10 | 11 | } 12 | 13 | my_page_template("Welcome to my webpage!",
Content of my page
) 14 | -------------------------------------------------------------------------------- /ide/vscode/wl-language/language-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | "blockComment": [""] 4 | }, 5 | "brackets": [ 6 | ["{", "}"], 7 | ["[", "]"], 8 | ["(", ")"] 9 | ], 10 | "autoClosingPairs": [ 11 | { "open": "{", "close": "}" }, 12 | { "open": "[", "close": "]" }, 13 | { "open": "(", "close": ")" }, 14 | { "open": "\"", "close": "\"" }, 15 | { "open": "'", "close": "'" } 16 | ], 17 | "surroundingPairs": [ 18 | ["{", "}"], 19 | ["[", "]"], 20 | ["(", ")"], 21 | ["\"", "\""], 22 | ["'", "'"] 23 | ], 24 | "folding": { 25 | "markers": { 26 | "start": "^\\s*", 41 | "patterns": [] 42 | } 43 | ] 44 | }, 45 | "keywords": { 46 | "patterns": [ 47 | { 48 | "name": "keyword.control.wl", 49 | "match": "\\b(if|else|while|for|in)\\b" 50 | }, 51 | { 52 | "name": "keyword.other.wl", 53 | "match": "\\b(procedure|let|include)\\b" 54 | }, 55 | { 56 | "name": "keyword.operator.wl", 57 | "match": "\\b(len|escape)\\b" 58 | } 59 | ] 60 | }, 61 | "constants": { 62 | "patterns": [ 63 | { 64 | "name": "constant.language.wl", 65 | "match": "\\b(none|true|false)\\b" 66 | } 67 | ] 68 | }, 69 | "strings": { 70 | "patterns": [ 71 | { 72 | "name": "string.quoted.double.wl", 73 | "begin": "\"", 74 | "end": "\"", 75 | "patterns": [ 76 | { 77 | "name": "constant.character.escape.wl", 78 | "match": "\\\\(n|t|r|\"|'|\\\\|x[0-9A-Fa-f]{2})" 79 | } 80 | ] 81 | }, 82 | { 83 | "name": "string.quoted.single.wl", 84 | "begin": "'", 85 | "end": "'", 86 | "patterns": [ 87 | { 88 | "name": "constant.character.escape.wl", 89 | "match": "\\\\(n|t|r|\"|'|\\\\|x[0-9A-Fa-f]{2})" 90 | } 91 | ] 92 | } 93 | ] 94 | }, 95 | "numbers": { 96 | "patterns": [ 97 | { 98 | "name": "constant.numeric.float.wl", 99 | "match": "\\b[0-9]+\\.[0-9]+\\b" 100 | }, 101 | { 102 | "name": "constant.numeric.integer.wl", 103 | "match": "\\b[0-9]+\\b" 104 | } 105 | ] 106 | }, 107 | "operators": { 108 | "patterns": [ 109 | { 110 | "name": "keyword.operator.append.wl", 111 | "match": "<<" 112 | }, 113 | { 114 | "name": "keyword.operator.comparison.wl", 115 | "match": "(==|!=|<=|>=)" 116 | }, 117 | { 118 | "name": "keyword.operator.relational.wl", 119 | "match": "(<|>)" 120 | }, 121 | { 122 | "name": "keyword.operator.assignment.wl", 123 | "match": "=" 124 | }, 125 | { 126 | "name": "keyword.operator.arithmetic.wl", 127 | "match": "(\\+|-|\\*|/|%)" 128 | } 129 | ] 130 | }, 131 | "system-variables": { 132 | "patterns": [ 133 | { 134 | "name": "variable.other.system.wl", 135 | "match": "\\$[a-zA-Z_][a-zA-Z0-9_]*" 136 | } 137 | ] 138 | }, 139 | "functions": { 140 | "patterns": [ 141 | { 142 | "name": "entity.name.function.wl", 143 | "match": "\\b[a-zA-Z_][a-zA-Z0-9_]*(?=\\s*\\()" 144 | } 145 | ] 146 | }, 147 | "html-tags": { 148 | "patterns": [ 149 | { 150 | "name": "meta.tag.html.wl", 151 | "begin": "(<)([a-zA-Z][a-zA-Z0-9]*)", 152 | "beginCaptures": { 153 | "1": { 154 | "name": "punctuation.definition.tag.begin.wl" 155 | }, 156 | "2": { 157 | "name": "entity.name.tag.wl" 158 | } 159 | }, 160 | "end": "(/>)|(>)", 161 | "endCaptures": { 162 | "1": { 163 | "name": "punctuation.definition.tag.self-closing.wl" 164 | }, 165 | "2": { 166 | "name": "punctuation.definition.tag.end.wl" 167 | } 168 | }, 169 | "patterns": [ 170 | { 171 | "name": "string.quoted.double.html.wl", 172 | "begin": "\"", 173 | "end": "\"", 174 | "patterns": [ 175 | { 176 | "include": "#embedded-expression" 177 | } 178 | ] 179 | }, 180 | { 181 | "name": "string.quoted.single.html.wl", 182 | "begin": "'", 183 | "end": "'", 184 | "patterns": [ 185 | { 186 | "include": "#embedded-expression" 187 | } 188 | ] 189 | }, 190 | { 191 | "include": "#embedded-expression" 192 | } 193 | ] 194 | }, 195 | { 196 | "name": "meta.tag.closing.html.wl", 197 | "match": "()", 198 | "captures": { 199 | "1": { 200 | "name": "punctuation.definition.tag.begin.wl" 201 | }, 202 | "2": { 203 | "name": "entity.name.tag.wl" 204 | }, 205 | "3": { 206 | "name": "punctuation.definition.tag.end.wl" 207 | } 208 | } 209 | } 210 | ] 211 | }, 212 | "embedded-expression": { 213 | "patterns": [ 214 | { 215 | "name": "meta.embedded.block.wl", 216 | "begin": "\\\\\\{", 217 | "end": "\\}", 218 | "patterns": [ 219 | { 220 | "include": "#expression-contents" 221 | } 222 | ] 223 | }, 224 | { 225 | "name": "meta.embedded.wl", 226 | "begin": "\\\\", 227 | "end": "(?=[\\s\"'/>])", 228 | "patterns": [ 229 | { 230 | "include": "#expression-contents" 231 | } 232 | ] 233 | } 234 | ] 235 | }, 236 | "expression-contents": { 237 | "patterns": [ 238 | { 239 | "include": "#keywords" 240 | }, 241 | { 242 | "include": "#strings" 243 | }, 244 | { 245 | "include": "#numbers" 246 | }, 247 | { 248 | "include": "#operators" 249 | }, 250 | { 251 | "include": "#system-variables" 252 | }, 253 | { 254 | "include": "#functions" 255 | }, 256 | { 257 | "include": "#constants" 258 | }, 259 | { 260 | "include": "#brackets" 261 | } 262 | ] 263 | }, 264 | "brackets": { 265 | "patterns": [ 266 | { 267 | "begin": "\\[", 268 | "end": "\\]", 269 | "patterns": [ 270 | { 271 | "include": "#keywords" 272 | }, 273 | { 274 | "include": "#strings" 275 | }, 276 | { 277 | "include": "#numbers" 278 | }, 279 | { 280 | "include": "#operators" 281 | }, 282 | { 283 | "include": "#system-variables" 284 | }, 285 | { 286 | "include": "#functions" 287 | }, 288 | { 289 | "include": "#constants" 290 | }, 291 | { 292 | "include": "#brackets" 293 | } 294 | ] 295 | }, 296 | { 297 | "begin": "\\{", 298 | "end": "\\}", 299 | "patterns": [ 300 | { 301 | "include": "#keywords" 302 | }, 303 | { 304 | "include": "#strings" 305 | }, 306 | { 307 | "include": "#numbers" 308 | }, 309 | { 310 | "include": "#operators" 311 | }, 312 | { 313 | "include": "#system-variables" 314 | }, 315 | { 316 | "include": "#functions" 317 | }, 318 | { 319 | "include": "#constants" 320 | }, 321 | { 322 | "include": "#brackets" 323 | } 324 | ] 325 | }, 326 | { 327 | "begin": "\\(", 328 | "end": "\\)", 329 | "patterns": [ 330 | { 331 | "include": "#keywords" 332 | }, 333 | { 334 | "include": "#strings" 335 | }, 336 | { 337 | "include": "#numbers" 338 | }, 339 | { 340 | "include": "#operators" 341 | }, 342 | { 343 | "include": "#system-variables" 344 | }, 345 | { 346 | "include": "#functions" 347 | }, 348 | { 349 | "include": "#constants" 350 | }, 351 | { 352 | "include": "#brackets" 353 | } 354 | ] 355 | } 356 | ] 357 | } 358 | } 359 | } -------------------------------------------------------------------------------- /LANGUAGE.md: -------------------------------------------------------------------------------- 1 | # WL Language Manual 2 | 3 | ## WL Programs 4 | 5 | A WL program is composed by zero or more statements, which may include 6 | 7 | 1. Expressions 8 | 2. If-else conditionals 9 | 3. While loops 10 | 4. For loops 11 | 5. Variable declarations 12 | 6. Procedure declarations 13 | 7. Code Blocks 14 | 8. External file inclusions 15 | 16 | Note that statements have no separators. To avoid ambiguities, it is useful to split statements over multiple lines. 17 | 18 | The output of a program is defined as the cumulative results of all expressions evaluated in the global scope. 19 | 20 | ## Expressions 21 | 22 | Programs operate on a set of types that one would expect from a scripting language: 23 | * integers 24 | * floats 25 | * booleans 26 | * none (equivalent to null) 27 | * strings 28 | * arrays 29 | * maps (equivalent to dicts in Python and associative arrays in PHP) 30 | 31 | ### Integers and Floats 32 | 33 | Integers are encoded as 64 bits signed, and therefore can encode the same value as an `int64_t` in C. 34 | 35 | Similarly, floats are also encoded over 64 bits and can encode the same precision of a `double` in C. 36 | 37 | The usual aritmethic operators are available 38 | 39 | ``` 40 | 3.5 + 4 41 | 3.5 - 4 42 | 3.5 * 4 43 | 3.5 / 4 44 | ``` 45 | 46 | Aritmethic operations between integers, with the exception of division, also return integers. Any operation involving a float, or a division, will also return a float. 47 | 48 | The modulo operator is also available for integers, which returns the division remainder 49 | 50 | ``` 51 | 101 % 10 52 | ``` 53 | 54 | You can use the unary plus and minus to express the sign of a numeric literal 55 | 56 | ``` 57 | +100 58 | -100 59 | ``` 60 | 61 | The plus can generally be omitted as it does nothing. 62 | 63 | ### Booleans 64 | 65 | Boolean values work as you would expect. These are the true and false literals: 66 | 67 | ``` 68 | true 69 | false 70 | ``` 71 | 72 | You can use comparison operators to produce true and false values 73 | 74 | ``` 75 | 1 < 2 76 | 1 > 2 77 | 1 == 2 78 | 1 != 2 79 | ``` 80 | 81 | Note that the `>=` and `<=` operators are not implemented yet as I never needed them up to now. The same goes for `and` and `or`. 82 | 83 | The ordering operators `<` and `>` may only be used on numeric values, while `==` and `!=` are allowed on any type. 84 | 85 | ### None 86 | 87 | The none value is usually referred to as "null" or "nil" in other languages. It's only quality is being equal to itself and may be used to encode the absence of a value. 88 | 89 | You can encode the none literal using the keyword 90 | ``` 91 | none 92 | ``` 93 | 94 | ### Strings 95 | 96 | Strings are sequence of characters delimited by single or double quotes. They can only contain printable ASCII characters (bytes from 32 to 127). 97 | 98 | ``` 99 | "Hello, world!" 100 | 'Hello, world!' 101 | ``` 102 | 103 | Any character outside the printable ASCII range must be encoded with its hexadecimal representation prefixed by `\x`. For instance, let's say we wanted to write the FF byte 104 | 105 | ``` 106 | "This byte is not printable: \xFF" 107 | ``` 108 | 109 | Some special characters that are not within the printable range may be escaped using their own specific escape sequence 110 | 111 | ``` 112 | "This is a newline \n" 113 | "This is an horizontal tab \t" 114 | "This is a carriage return \r" 115 | ``` 116 | 117 | Although the `'` and `"` characters are printable, they may interfere with the string delimiters, therefore strings the contain `'` characters should be delimited with `"` and viceversa. When avoiding the ambiguity is not possible, the `'` and `"` may themselves be escaped 118 | 119 | ``` 120 | " This is a double quote \" " 121 | ' This is a single quote \' ' 122 | ``` 123 | 124 | Since the `\` character is used to escape other character, when used as its own character it also needs to be escaped 125 | 126 | ``` 127 | " This is a backslash \\ " 128 | ``` 129 | 130 | Note that the requirement that strings only contain printable characters implies that strings can't span multiple lines of source code. In other words, this doesn't work: 131 | 132 | ``` 133 | "This 134 | is 135 | not 136 | valid" 137 | ``` 138 | 139 | ### Arrays 140 | 141 | Arrays represent an ordered sequence of values which may have different types from each other. They are defined using square brackets and commas as separators. 142 | 143 | ``` 144 | [1, 2.3, none] 145 | ``` 146 | 147 | Trailing commas are supported 148 | 149 | ``` 150 | [1, 2, 3,] 151 | ``` 152 | 153 | To insert new values into an array you use the shovel operator 154 | 155 | ``` 156 | [1, 2, 3] << 4 157 | ``` 158 | 159 | When evaluated into the global scope, arrays are output as the concatenation of their elements, which means they are useful to perform lazy concatenation of strings. 160 | 161 | To select an element by its index (indices start at zero) you use the []-style selection. For instance the following returns `2`: 162 | 163 | ``` 164 | [1, 2, 3][1] 165 | ``` 166 | 167 | ### Maps 168 | 169 | Maps are the equivalent of dicts in Python and use a similar syntax: 170 | 171 | ``` 172 | +{ 'name': 'Alice', 'color': 'red' } 173 | ``` 174 | 175 | They are defined within curly braces and contain a list of zero or more key-value pairs separated by colons and commas. The `+` at the start is not part of the map, it's only used in the global scope to disambiguate with curly braces used for creating scopes and maps. By using an unary `+` we make explicit that we are writing an expression. Map objects are generally not considered as printable, and therefore defining them as we are would just output the string ``. 176 | 177 | Just like arrays, maps allow trailing commas: 178 | 179 | ``` 180 | +{ 'name': 'Alice', 'color': 'red', } 181 | ``` 182 | 183 | Map keys can have any type (except for other maps and arrays), but when a given key is a string and a valid identifier name, the quotes can be dropped: 184 | 185 | ``` 186 | +{ name: 'Alice', color: 'red' } 187 | ``` 188 | 189 | A valid identifier name is any sequence of digits, letters and underscores that does not start with a digit. 190 | 191 | To select an item from a map, you can use the [] notation 192 | 193 | ``` 194 | +{ name: 'Alice', color: 'red' }["name"] 195 | ``` 196 | 197 | or the dot notation if the key you are selecting is a valid identifier 198 | 199 | ``` 200 | +{ name: 'Alice', color: 'red' }.name 201 | ``` 202 | 203 | You can assign new values to the given keys by using the `=` operator 204 | 205 | ``` 206 | +{ name: 'Alice', color: 'red' }["name"] = 'Bob' 207 | +{ name: 'Alice', color: 'red' }.name = 'Bob' 208 | ``` 209 | 210 | ## Variables 211 | 212 | You can create variables to reuse results of expressions multiple times. Variables are declared using the `let` keyword and values can be assigned to them using the `=` operator 213 | 214 | ``` 215 | let name 216 | 217 | name = "Alice" 218 | ``` 219 | 220 | You can also declare a variable and assign a value to it in the same statement 221 | 222 | ``` 223 | let name = "Alice" 224 | ``` 225 | 226 | If you didn't assign a value to a variable, its value will be `none`. 227 | 228 | You can assign values to a variable multiple times, and the values may have different types 229 | 230 | ``` 231 | let name 232 | 233 | name = "Alice" 234 | name = "Bob" 235 | ``` 236 | 237 | Whenever you would use a numeric, string or any other literal, you name the variable holding the value instead. 238 | 239 | ## Code Blocks 240 | 241 | You can group multiple statements into one code block statement using curly braces 242 | 243 | ``` 244 | { 245 | let a = 2 246 | 3 * a 247 | } 248 | ``` 249 | 250 | This has a couple effects. The first one, it allows you to treat multiple statements as one. This will come in handy with if-else statements. The second one, is that code blocks create variable "scopes". When a variable is declared within a scope, it can only be accessed by that scope or children scopes. 251 | 252 | ``` 253 | { 254 | let a = 2 255 | "a is accessible here" 256 | 257 | { 258 | "It's also accessible from here" 259 | } 260 | } 261 | 262 | "But not here" 263 | ``` 264 | 265 | This allows one to use the same variable name by declaring different scopes for it 266 | 267 | ``` 268 | { 269 | let name = "Alice" 270 | } 271 | 272 | { 273 | let name = "Bob" 274 | } 275 | ``` 276 | 277 | If these variables were declared within the same scope, the program would be invalid. 278 | 279 | Shadowing is also supported. You can declare a variable over another from a parent scope 280 | 281 | ``` 282 | let name = "Alice" 283 | 284 | { 285 | let name = "Bob" 286 | name 287 | } 288 | 289 | name 290 | ``` 291 | 292 | This program will print "BobAlice". The inner scope declares a new verstion of `name` which *shadows* the first version. When the inner scope completes, the first version of `name` is not shadowed anymore and can be used again. 293 | 294 | ## If-Else Conditionals 295 | 296 | You can execute an optional blocks of code based on whether an expression is true or not by using an if statement: 297 | 298 | ``` 299 | let a = 3 300 | 301 | if a > 5: { 302 | "a is indeed greater than 5" 303 | } 304 | ``` 305 | 306 | If you also want to execute an optional block of code when the condition is not true, you can add the block after the `else` keyword 307 | 308 | ``` 309 | let a = 3 310 | 311 | if a > 5: { 312 | "a is indeed greater than 5" 313 | } else { 314 | "a is not greater than 5..." 315 | } 316 | ``` 317 | 318 | The curly braces are used to define code blocks, which means you can omit the braces when the block is only made by one statement 319 | 320 | ``` 321 | let a = 3 322 | 323 | if a > 5: 324 | "a is indeed greater than 5" 325 | else 326 | "a is not greater than 5..." 327 | ``` 328 | 329 | An implication of this is that you can chain multiple if statements like this: 330 | 331 | ``` 332 | let a = 3 333 | 334 | if a > 5: { 335 | "a is indeed greater than 5" 336 | } else if a > 4: { 337 | "a is greater than 4" 338 | } else if a > 3: { 339 | "a is greater than 3" 340 | } else { 341 | "a is not greater than 5..." 342 | } 343 | ``` 344 | 345 | Note that variables declared within if-else blocks will not be accessible in the parent scope 346 | 347 | ## While loops 348 | 349 | While loops are similar to if statements, except they evaluate their body while the condition is true 350 | 351 | ``` 352 | let i = 0 353 | while i < 3: { 354 | "Print me" 355 | i = i + 1 356 | } 357 | ``` 358 | 359 | This will print "Print me" three times. 360 | 361 | ## For loops 362 | 363 | For loops are similar to while loop except they are intended to read elements contained by an array or map. 364 | 365 | The following code will iterate over the elements of the array and print them 366 | 367 | ``` 368 | let A = [1, 2, 3] 369 | 370 | for element in my_array: { 371 | element 372 | } 373 | ``` 374 | 375 | If you want to keep track of the current iteration index, you can declare a second iteration variable 376 | 377 | ``` 378 | let A = [1, 2, 3] 379 | 380 | for element, index in my_array: { 381 | element 382 | index 383 | } 384 | ``` 385 | 386 | In a similar way you can iterate over maps 387 | 388 | ``` 389 | let A = { name: 'Alice', color: 'red' } 390 | 391 | for key in A: { 392 | key 393 | } 394 | ``` 395 | 396 | The first iteration variable returns the current key. To get the value associated to that key in the map, you need to read it explicitly using the key. 397 | 398 | If, while reading over a map, you want to access the current iteration index, you can add a second iteration variable 399 | 400 | ``` 401 | let A = { name: 'Alice', color: 'red' } 402 | 403 | for key, index in A: { 404 | key 405 | index 406 | } 407 | ``` 408 | 409 | ## Procedures 410 | 411 | Unlike other languages, WL does not implement functions. It does implement procedures, which share commonalities but are overall different. 412 | 413 | Here is an example of a procedure: 414 | 415 | ``` 416 | procedure greet(name) { 417 | "Hello from " 418 | name 419 | "!" 420 | } 421 | 422 | greet("Francesco") 423 | ``` 424 | 425 | The output of the procedure is the cumulative output of all expressions it evaluates. 426 | 427 | Note that you may call procedures before their declaration 428 | 429 | ``` 430 | do_something() 431 | 432 | procedure do_something() { 433 | "works!" 434 | } 435 | ``` 436 | 437 | Procedures may call themselves recursively 438 | 439 | ``` 440 | procedure factorial(n) { 441 | if n == 0: { 442 | 1 443 | } else { 444 | n * factorial(n-1) 445 | } 446 | } 447 | 448 | factorial(10) 449 | ``` 450 | 451 | ## HTML literals 452 | 453 | HTML literals are a type of expression, but they are complex enough that they warrant their own section. 454 | 455 | Generally speaking, HTML elements are valid expressions 456 | 457 | ``` 458 |

Hello, world!

459 | ``` 460 | 461 | which evaluate to a string containing that HTML. The content of an element can be an arbitrary string or nested HTML elements. 462 | 463 | You can render variable values or any expression inside the HTML using the `\{}` notation: 464 | 465 | ``` 466 | let name = "Alice" 467 | 468 |

My name is \{name} and my favourite number is \{99 + 1}!

469 | ``` 470 | 471 | You can also evaluate optional HTML elements using the `\if` construct 472 | 473 | ``` 474 | let a = 5 475 | 476 |
477 | \if a < 10: 478 |

a is lower than 10

479 | else 480 |

a isn't lower than 10

481 |
482 | ``` 483 | 484 | And iterate over elements of arrays and maps using `\for` 485 | 486 | ``` 487 | let items = [1, 2, 3] 488 | 489 | 493 | ``` 494 | 495 | In reality, the `\` character works by interrupting the HTML content string to evaluate any one WL statement. The output of that statement is then added to the HTML element's output. 496 | 497 | Since HTML elements are just expressions, you may assign them to variables 498 | 499 | ``` 500 | let items = [1, 2, 3] 501 | 502 | let list = 503 | 507 | 508 | list 509 | ``` 510 | 511 | Evaluating dynamic content within the opening tag is also allowed 512 | 513 | ``` 514 | let element_id = "mydiv" 515 | 516 |
517 | ``` 518 | 519 | You may omit the closing tag of any element by using this syntax: 520 | 521 | ``` 522 |
523 | ``` 524 | 525 | Note that WL treats all elements the same way and does not apply different behavior based on the specific tag it's parsing. For instance most browsers will allor you to have a single open tag `
` with no closing one since `br` doesn't expect children elements. This would be incorrect in WL. You need to either write the element as `

` or as `
`. 526 | 527 | To avoid XSS attacks, you can use the `escape` operator to escape any HTML element. The following script 528 | 529 | ``` 530 | escape click me 531 | ``` 532 | 533 | Will output 534 | 535 | ``` 536 | <a href="website.com">click me</a> 537 | ``` 538 | 539 | ## File Inclusion 540 | 541 | WL allows you to import all output, variables, routines from an external file to your script using the `include` statement. 542 | 543 | Say you have a file `other.wl` that contains the following text 544 | 545 | ``` 546 | 547 | "Some output here" 548 | 549 | let A = 5 550 | 551 | ``` 552 | 553 | Any other file may include `other.wl` to use its contents 554 | 555 | ``` 556 | include "other.wl" 557 | 558 | "The A variable is accessible here: " 559 | A 560 | ``` 561 | 562 | ## External Symbols 563 | 564 | WL programs may reference external symbols (variables or functions) defined by the host program. These symbols behave like variables and procedures, except they don't need to be declared and their names start with `$`. For instance, you could have a `$platform` symbol return the name of the current platform (as in "Linux" or "Windows") 565 | 566 | ``` 567 |

The process is running on a \$platform machine

568 | ``` 569 | --------------------------------------------------------------------------------