├── .gitignore ├── .gitmodules ├── LICENSE ├── Makefile ├── Makefile-cfiles ├── README.md ├── libctrans ├── .gitignore ├── Makefile ├── README.md ├── copyright-fork.txt └── src │ ├── Makefile │ └── ctrans │ ├── block.fork │ ├── blockexpr.fork │ ├── csym.fork │ ├── ctrans.fork │ ├── globexpr.fork │ ├── utils.fork │ └── version.fork ├── libfork ├── .gitignore ├── Makefile ├── README.md ├── copyright-c.txt ├── copyright-fork.txt ├── examples │ └── old-examples │ │ ├── aliaxample.fork │ │ ├── argxample.fork │ │ ├── bufxample.fork │ │ ├── callgrind │ │ ├── cdump │ │ ├── charxample.fork │ │ ├── charxample2.fork │ │ ├── charxample3.fork │ │ ├── dbg │ │ ├── dynxample.fork │ │ ├── ex │ │ ├── fordimpxample.fork │ │ ├── fordxample.fork │ │ ├── gdbg │ │ ├── hashxample.fork │ │ ├── hashxample2.fork │ │ ├── kvxample.fork │ │ ├── lel.txt │ │ ├── lexample.fork │ │ ├── mapxample2.fork │ │ ├── massif │ │ ├── memchk │ │ ├── method.txt │ │ ├── pathxample.fork │ │ ├── sdirexample.fork │ │ ├── semxample.fork │ │ ├── sexample.fork │ │ └── splitxample.fork └── src │ ├── Makefile │ ├── about │ └── version.fork │ ├── args │ └── args.fork │ ├── c │ ├── c.fork │ └── cstreams.c │ ├── dyn │ ├── dyn.fork │ └── loadlib.c │ ├── err │ └── error.fork │ ├── fs │ ├── dir.fork │ ├── file.fork │ ├── filefcn.c │ ├── lineno.fork │ └── paths.fork │ ├── hash │ ├── hash.fork │ ├── hashiter.fork │ └── hashnum.fork │ ├── io │ ├── streams.fork │ └── ttystream.fork │ ├── kv │ └── keyvaluelist.fork │ ├── list │ └── list.fork │ ├── map │ ├── iter.fork │ └── map.fork │ ├── math │ └── math.fork │ ├── mem │ ├── alloc.fork │ ├── buffer.fork │ └── memmove.fork │ ├── memutils │ ├── freepool.fork │ └── ref.fork │ ├── misc │ ├── numrepr.fork │ └── utils.fork │ ├── pair │ └── pair.fork │ ├── proc │ └── proc.fork │ ├── rt │ └── rt.fork │ ├── set │ ├── set.fork │ └── setiter.fork │ ├── sort │ └── sort.fork │ ├── tty │ ├── console.fork │ └── outint.c │ ├── txt │ ├── charstash.fork │ ├── strings.fork │ └── tokenizer.fork │ └── vect │ └── vector.fork ├── libforkparse ├── .gitignore ├── Makefile ├── README.md ├── copyright-fork.txt ├── fork.ebnf ├── selftest.sh └── src │ ├── Makefile │ ├── ast │ ├── ast.fork │ ├── astfn.fork │ ├── dump.fork │ ├── issue.fork │ ├── lex.fork │ ├── psymbols.fork │ ├── symbols.fork │ └── tokens.fork │ └── parser │ ├── dump.fork │ ├── export-ford.fork │ ├── import-ford.fork │ ├── parser.fork │ ├── sema-aliases.fork │ ├── sema-base.fork │ ├── sema-decls.fork │ ├── sema-expressions.fork │ ├── sema-functions.fork │ ├── sema-resolver.fork │ ├── synt-base.fork │ ├── synt-expressions.fork │ └── version.fork ├── syntax ├── atom │ └── grammars │ │ └── fork.cson ├── fork.xml └── vscode │ └── forklang-vscode │ ├── CHANGELOG.md │ ├── README.md │ ├── language-configuration.json │ ├── package.json │ ├── syntaxes │ └── fork.tmLanguage.json │ └── vsc-extension-quickstart.md └── tools ├── forktree └── parsedir.fork └── transmod └── transmod.fork /.gitignore: -------------------------------------------------------------------------------- 1 | build/* 2 | examples/*.txt 3 | examples/*.elf 4 | examples/*.old 5 | tests/*.err 6 | core.* 7 | syntax/vscode/forklang-vscode/.vscode -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcilloni/fork/ec7a53f0dc6258491f496c2fe3fa4f09b9e57b82/.gitmodules -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PWD = $(shell pwd) 2 | BUILD = $(PWD)/build 3 | CURSTAGE = $(BUILD)/current 4 | STAGE1 = $(BUILD)/stage1 5 | STAGE2 = $(BUILD)/stage2 6 | STAGE3 = $(BUILD)/stage3 7 | 8 | TOOLSDIR = $(PWD)/tools/ 9 | 10 | LIBFORK = $(PWD)/libfork/ 11 | LIBFORKPARSE = $(PWD)/libforkparse/ 12 | LIBCTRANS = $(PWD)/libctrans/ 13 | 14 | RELDIRNAME = fork-release 15 | RELDIR = $(PWD)/$(RELDIRNAME) 16 | 17 | ifndef TRNS 18 | TRNS = transmod 19 | endif 20 | 21 | ifndef TAR 22 | TAR=tar 23 | endif 24 | 25 | ifndef AR 26 | AR=ar 27 | endif 28 | 29 | ifndef RANLIB 30 | RANLIB=ranlib 31 | endif 32 | 33 | MACHINE = $(shell uname -m) 34 | 35 | ifeq ($(MACHINE), amd64) 36 | AMD64 = yes 37 | endif 38 | 39 | ifdef AMD64 40 | ifeq (,$(findstring CYGWIN,$(UNAME))) 41 | FPIC = -fPIC 42 | endif 43 | endif 44 | 45 | ifndef PKGNAME 46 | PKGNAME=$(RELDIRNAME).txz 47 | endif 48 | 49 | CFLAGS = -Wno-incompatible-pointer-types -Wno-implicit-function-declaration -Wno-incompatible-function-pointer-types -w -g -std=c99 -D_POSIX_C_SOURCE=200112L 50 | 51 | .PHONY: all clean package package-base package-cross bootstrap stage1 stage2 \ 52 | stage3 libfork libforkparse libctrans stage stage-libctrans stage-libfork \ 53 | stage-libfork stage-tools 54 | 55 | all: bootstrap 56 | 57 | package: 58 | $(MAKE) bootstrap 59 | $(MAKE) STAGE=$(STAGE3) package-base 60 | 61 | package-cross: 62 | $(MAKE) stage1 63 | $(MAKE) STAGE=$(STAGE1) package-base 64 | 65 | package-base: 66 | mkdir -p $(RELDIR) 67 | cp -r $(STAGE)/ford $(RELDIR) 68 | cp $(STAGE)/rt.o $(RELDIR) 69 | cp $(STAGE)/libfork.a $(RELDIR) 70 | cp $(STAGE)/libforkparse.a $(RELDIR) 71 | cp $(STAGE)/libctrans.a $(RELDIR) 72 | cp $(STAGE)/forktree $(RELDIR) 73 | cp $(STAGE)/transmod $(RELDIR) 74 | cp $(PWD)/LICENSE $(RELDIR) 75 | cd $(PWD) && $(TAR) -cJf $(PKGNAME) $(RELDIRNAME) 76 | rm -r $(RELDIR) 77 | 78 | bootstrap: 79 | $(MAKE) stage1 80 | $(MAKE) stage2 81 | $(MAKE) stage3 82 | 83 | stage1: 84 | $(MAKE) BUILD=$(STAGE1) stage 85 | 86 | stage2: 87 | $(MAKE) TRNS=$(STAGE1)/transmod BUILD=$(BUILD)/stage2 stage 88 | 89 | stage3: 90 | $(MAKE) TRNS=$(STAGE2)/transmod BUILD=$(BUILD)/stage3 stage 91 | 92 | stage: 93 | $(MAKE) stage-libfork 94 | $(MAKE) stage-libforkparse 95 | $(MAKE) stage-libctrans 96 | $(MAKE) stage-tools 97 | 98 | stage-libctrans: 99 | $(MAKE) -C $(LIBCTRANS) 100 | $(MAKE) libctrans 101 | 102 | stage-libfork: 103 | $(MAKE) -C $(LIBFORK) clean 104 | $(MAKE) libfork 105 | 106 | stage-libforkparse: 107 | $(MAKE) -C $(LIBFORKPARSE) clean 108 | $(MAKE) libforkparse 109 | 110 | stage-tools: 111 | FORDPATHS=$(BUILD)/ford $(TRNS) -n forktree -co $(BUILD)/cfiles $(TOOLSDIR)/forktree 112 | $(CC) $(CFLAGS) -o $(BUILD)/forktree $(BUILD)/cfiles/forktree.c $(BUILD)/libforkparse.a $(BUILD)/libfork.a $(BUILD)/rt.o 113 | FORDPATHS=$(BUILD)/ford $(TRNS) -n transmod -co $(BUILD)/cfiles $(TOOLSDIR)/transmod 114 | $(CC) $(CFLAGS) -o $(BUILD)/transmod $(BUILD)/cfiles/transmod.c $(BUILD)/libctrans.a $(BUILD)/libforkparse.a $(BUILD)/libfork.a $(BUILD)/rt.o 115 | 116 | clean: 117 | $(MAKE) -C libfork clean 118 | rm -rf $(BUILD) 119 | rm -rf fork-release 120 | rm -f fork-release.txz 121 | rm -f fork-cfiles.txz 122 | 123 | libfork: 124 | $(MAKE) -C $(LIBFORK) 125 | 126 | libforkparse: 127 | $(MAKE) FORDPATHS=$(BUILD)/ford -C $(LIBFORKPARSE) 128 | 129 | libctrans: 130 | $(MAKE) FORDPATHS=$(BUILD)/ford -C $(LIBCTRANS) 131 | 132 | pack-cout: 133 | if test ! -d $(BUILD)/stage3; then $(MAKE); fi; \ 134 | cp -r $(BUILD)/stage3/cfiles fork-cfiles && \ 135 | cp Makefile-cfiles fork-cfiles/Makefile && \ 136 | find fork-cfiles -name "*.o" -delete && \ 137 | tar cvf - fork-cfiles | xz > fork-cfiles.txz && \ 138 | rm -rf fork-cfiles 139 | -------------------------------------------------------------------------------- /Makefile-cfiles: -------------------------------------------------------------------------------- 1 | UNAME := $(shell uname) 2 | 3 | ifeq ($(UNAME), Linux) 4 | LDFLAGS += -ldl 5 | endif 6 | 7 | SOURCES := $(shell find libfork libforkparse libctrans -name '*.c') 8 | 9 | all: 10 | $(CC) -w -O2 -std=c99 -D_POSIX_C_SOURCE=200112L -ldl -o forktree rt.c forktree.c $(SOURCES) $(LDFLAGS) 11 | $(CC) -w -O2 -std=c99 -D_POSIX_C_SOURCE=200112L -ldl -o transmod rt.c transmod.c $(SOURCES) $(LDFLAGS) -------------------------------------------------------------------------------- /libctrans/.gitignore: -------------------------------------------------------------------------------- 1 | build/* 2 | build.1/* 3 | build.2/* 4 | ctrans-release* 5 | examples/*.txt 6 | examples/*.elf 7 | examples/*.old 8 | tests/*.err 9 | core.* 10 | -------------------------------------------------------------------------------- /libctrans/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean tests st 2 | 3 | all: clean 4 | $(MAKE) -C src 5 | 6 | transl: 7 | $(MAKE) -C src transl 8 | 9 | clean: 10 | rm -rf build 11 | -------------------------------------------------------------------------------- /libctrans/README.md: -------------------------------------------------------------------------------- 1 | # libctrans 2 | 3 | 4 | *libctrans* is a library that implements a transpiler for compiling Fork code to C99. 5 | 6 | This is largely a WIP project, and it's pretty far away from release, so expect lots of bugs. 7 | 8 | Contributions are always accepted. 9 | 10 | ## License 11 | 12 | Mozilla Public License (MPL), version 2. 13 | -------------------------------------------------------------------------------- /libctrans/copyright-fork.txt: -------------------------------------------------------------------------------- 1 | # libctrans, Fork to C transpiler library 2 | # Copyright (C) Marco Cilloni 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | -------------------------------------------------------------------------------- /libctrans/src/Makefile: -------------------------------------------------------------------------------- 1 | BUILD = $(shell pwd)/../build/ 2 | CFILES = $(BUILD)/cfiles/libctrans 3 | FORDS = $(BUILD)/ford/ 4 | 5 | ifndef TRNS 6 | TRNS = transmod 7 | endif 8 | 9 | ifdef FORDPATHS 10 | TRNSCMD = env FORDPATHS=$(FORDPATHS):$(FORDS) $(TRNS) -fo $(FORDS) -co $(CFILES) 11 | else 12 | TRNSCMD = env FORDPATHS=$(FORDS) $(TRNS) -fo $(FORDS) -co $(CFILES) 13 | endif 14 | 15 | ifndef AR 16 | AR=ar 17 | endif 18 | 19 | ifndef RANLIB 20 | RANLIB=ranlib 21 | endif 22 | 23 | MACHINE = $(shell uname -m) 24 | 25 | ifeq ($(MACHINE), amd64) 26 | AMD64 = yes 27 | endif 28 | 29 | ifdef AMD64 30 | ifeq (,$(findstring CYGWIN,$(UNAME))) 31 | FPIC = -fPIC 32 | endif 33 | endif 34 | 35 | CFLAGS = -Wno-incompatible-pointer-types -Wno-implicit-function-declaration -Wno-incompatible-function-pointer-types -w -g -std=c99 -D_POSIX_C_SOURCE=200112L 36 | 37 | SONAME = 'libctrans.so' 38 | ARNAME = 'libctrans.a' 39 | 40 | .PHONY: all clean 41 | 42 | all: 43 | $(MAKE) transl 44 | $(MAKE) cc-ar 45 | 46 | clean: 47 | rm -rf $(BUILD) 48 | 49 | transl: 50 | mkdir -p $(BUILD) 51 | mkdir -p $(FORDS) 52 | mkdir -p $(CFILES) 53 | $(TRNSCMD) ctrans 54 | 55 | cc-ar: 56 | cd $(CFILES) && $(CC) -c $(CFLAGS) $(CFILES)/*.c 57 | @printf "AR\t\t%s\n" $(ARNAME) 58 | @ $(AR) rc $(BUILD)/$(ARNAME) $(CFILES)/*.o 59 | @ $(RANLIB) $(BUILD)/$(ARNAME) 60 | -------------------------------------------------------------------------------- /libctrans/src/ctrans/globexpr.fork: -------------------------------------------------------------------------------- 1 | # libctrans, Fork to C transpiler library 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module ctrans 12 | 13 | 14 | import ast 15 | import mem 16 | import proc 17 | import tty 18 | 19 | 20 | method Transl.globDotExpr(pexpr ptr ast:PExpr) 21 | 22 | mut e1 = (val pexpr'node'leaves.get(0)) 23 | mut e2 = (val pexpr'node'leaves.get(1)) 24 | 25 | mut targetType = e1'type 26 | 27 | if targetType.isPtr() 28 | targetType = targetType'retType 29 | /if 30 | 31 | mut typeName = symMod(targetType'moduleName, targetType'name) 32 | mut methName = (e2'node'value) 33 | 34 | me'vars.addMethSym(typeName, methName) 35 | 36 | mem:free(typeName) 37 | /method 38 | 39 | 40 | 41 | method Transl.globExpr(root ptr ast:PRoot, pexpr ptr ast:PExpr) 42 | 43 | mut value = pexpr'node'value 44 | 45 | if pexpr'opType == ast:NUMBER 46 | me'vars.addInt(value) 47 | 48 | return 49 | /if 50 | 51 | if pexpr'opType == ast:STRING 52 | me'vars.addCStr((value)) 53 | return 54 | /if 55 | 56 | if pexpr'opType == ast:ID 57 | 58 | mut name = (value) 59 | mut modName ptr uint8 = root'moduleName? => root'moduleName'name || null 60 | mut fDecl = root'node'syms.get(name) 61 | 62 | if fDecl? and not fDecl'declOnly and (pexpr).findSym(name) == fDecl'type 63 | me'vars.addSymName(modName, name) 64 | else 65 | me'vars.add(name) 66 | /if 67 | 68 | return 69 | /if 70 | 71 | 72 | if pexpr'opType == ast:NULL 73 | me'vars.add("(void*) 0") 74 | 75 | return 76 | /if 77 | 78 | if pexpr'opType == ast:TRUE 79 | me'vars.add("1") 80 | 81 | return 82 | /if 83 | 84 | if pexpr'opType == ast:FALSE 85 | me'vars.add("0") 86 | 87 | return 88 | /if 89 | 90 | if pexpr'opType == ast:COLON 91 | mut modName = ((val pexpr'node'leaves.get(0))'value) 92 | mut name = ((val pexpr'node'leaves.get(1))'value) 93 | 94 | me'vars.addSymName(modName, name) 95 | 96 | return 97 | /if 98 | 99 | if pexpr'opType == ast:APOS 100 | mut e1 = (val pexpr'node'leaves.get(0)) 101 | mut e2 = (val pexpr'node'leaves.get(1)) 102 | 103 | me.globExpr(root, e1) 104 | 105 | me'vars.add((e1'type? and e1'type'type == ast:TYPE_PTR) => "->" || ".") 106 | 107 | me'vars.add((e2'node'value)) 108 | 109 | return 110 | /if 111 | 112 | if pexpr'opType == ast:SIZE 113 | me'vars.add("sizeof(") 114 | me.wrapType(me'vars, pexpr'sizeType, -1) 115 | me'vars.add(")") 116 | 117 | return 118 | /if 119 | 120 | if pexpr'opType == ast:CAST 121 | mut expr = (val pexpr'node'leaves.get(0)) 122 | 123 | me'vars.add("((") 124 | me.wrapType(me'vars, pexpr'type, -1) 125 | me'vars.add(") ") 126 | 127 | me.globExpr(root, expr) 128 | 129 | me'vars.add(")") 130 | 131 | return 132 | /if 133 | 134 | if pexpr'opType == ast:OPAR 135 | mut toCall = (val pexpr'node'leaves.get(0)) 136 | mut methCall = toCall'opType == ast:DOT 137 | 138 | if methCall 139 | me.globDotExpr(toCall) 140 | else 141 | me.globExpr(root, toCall) 142 | /if 143 | 144 | me'vars.add("(") 145 | 146 | mut len = pexpr'node'leaves.len() 147 | 148 | # add me parameter 149 | if methCall 150 | mut target = (val toCall'node'leaves.get(0)) 151 | mut notPtr = not target'type.isPtr() 152 | 153 | if notPtr 154 | me'vars.add("&(") 155 | /if 156 | 157 | me.globExpr(root, target) 158 | 159 | if notPtr 160 | me'vars.add(")") 161 | /if 162 | 163 | if len > 1 164 | me'vars.addWord(",") 165 | /if 166 | /if 167 | 168 | mut i uintptr = 1 169 | 170 | while i < len 171 | mut param = (val pexpr'node'leaves.get(i)) 172 | 173 | if i > 1 174 | me'vars.addWord(",") 175 | /if 176 | 177 | me.globExpr(root, param) 178 | i++ 179 | /while 180 | 181 | me'vars.add(")") 182 | 183 | return 184 | /if 185 | 186 | if pexpr'opType == ast:OBRAC 187 | mut e1 = (val pexpr'node'leaves.get(0)) 188 | mut e2 = (val pexpr'node'leaves.get(1)) 189 | 190 | me'vars.add("(") 191 | 192 | me.globExpr(root, e1) 193 | 194 | me'vars.add(")[") 195 | 196 | me.globExpr(root, e2) 197 | 198 | me'vars.add("]") 199 | 200 | return 201 | /if 202 | 203 | if pexpr'opType == ast:DQUEST 204 | mut e1 = (val pexpr'node'leaves.get(0)) 205 | mut e2 = (val pexpr'node'leaves.get(1)) 206 | 207 | me'vars.add("(") 208 | 209 | me.globExpr(root, e1) 210 | 211 | me'vars.add(" != (void*)0) ? (") 212 | 213 | me.globExpr(root, e1) 214 | 215 | me'vars.add(") : (") 216 | 217 | me.globExpr(root, e2) 218 | 219 | me'vars.add(")") 220 | 221 | return 222 | /if 223 | 224 | if pexpr'opType == ast:FATARROW 225 | mut e1 = (val pexpr'node'leaves.get(0)) 226 | mut e2 = (val pexpr'node'leaves.get(1)) 227 | mut e3 = (val pexpr'node'leaves.get(2)) 228 | 229 | me'vars.add("(") 230 | 231 | me.globExpr(root, e1) 232 | 233 | me'vars.add(") ? (") 234 | 235 | me.globExpr(root, e2) 236 | 237 | me'vars.add(") : (") 238 | 239 | me.globExpr(root, e3) 240 | 241 | me'vars.add(")") 242 | 243 | return 244 | /if 245 | 246 | if pexpr'opType == ast:DEC 247 | mut e = (val pexpr'node'leaves.get(0)) 248 | me'vars.add("--") 249 | 250 | me.globExpr(root, e) 251 | return 252 | /if 253 | 254 | if pexpr'opType == ast:INC 255 | mut e = (val pexpr'node'leaves.get(0)) 256 | 257 | me'vars.add("++") 258 | 259 | me.globExpr(root, e) 260 | return 261 | /if 262 | 263 | if pexpr'opType == ast:QUEST 264 | mut e = (val pexpr'node'leaves.get(0)) 265 | 266 | me'vars.add("(") 267 | me.globExpr(root, e) 268 | 269 | me'vars.add(" != (void*) 0)") 270 | 271 | return 272 | /if 273 | 274 | if isBinOp(pexpr'opType) or pexpr'opType == ast:MINUS 275 | mut e1 = (val pexpr'node'leaves.get(0)) 276 | mut e2 = (val pexpr'node'leaves.get(1)) 277 | 278 | if pexpr'opType == ast:POW 279 | me'vars.add("math$__forkpow(") 280 | me.globExpr(root, e1) 281 | me'vars.add(", ") 282 | me.globExpr(root, e2) 283 | me'vars.add(")") 284 | 285 | return 286 | /if 287 | 288 | me'vars.add("(") 289 | me.globExpr(root, e1) 290 | me'vars.addChar(32) 291 | me'vars.add(opConv(pexpr'opType)) 292 | me'vars.addChar(32) 293 | me.globExpr(root, e2) 294 | me'vars.add(")") 295 | 296 | return 297 | /if 298 | 299 | #assume prefix unary now 300 | 301 | mut e = (val pexpr'node'leaves.get(0)) 302 | me'vars.add(opConv(pexpr'opType)) 303 | me'vars.add("(") 304 | me.globExpr(root, e) 305 | me'vars.add(")") 306 | 307 | /method 308 | -------------------------------------------------------------------------------- /libctrans/src/ctrans/utils.fork: -------------------------------------------------------------------------------- 1 | # libctrans, Fork to C transpiler library 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module ctrans 12 | 13 | 14 | import ast 15 | import mem 16 | import proc 17 | import tty 18 | import txt 19 | 20 | 21 | method txt:Charstash.addCStr(str ptr uint8) 22 | me.add("(uint8_t*)\"") 23 | 24 | mut ch uint8 = 0 25 | 26 | while (ch = val str) != 0 27 | 28 | if ch == 7 29 | me.add("\\a") 30 | else 31 | if ch == 8 32 | me.add("\\b") 33 | else 34 | if ch == 12 35 | me.add("\\f") 36 | else 37 | if ch == 10 38 | me.add("\\n") 39 | else 40 | if ch == 13 41 | me.add("\\r") 42 | else 43 | if ch == 9 44 | me.add("\\t") 45 | else 46 | if ch == 11 47 | me.add("\\v") 48 | else 49 | if ch == 92 50 | me.add("\\\\") 51 | else 52 | if ch == 39 53 | me.add("\\'") 54 | else 55 | if ch == 34 56 | me.add("\\\"") 57 | else 58 | if ch == 63 59 | me.add("\\?") 60 | else 61 | me.addChar(ch) 62 | /if 63 | /if 64 | /if 65 | /if 66 | /if 67 | /if 68 | /if 69 | /if 70 | /if 71 | /if 72 | /if 73 | 74 | str++ 75 | /while 76 | 77 | me.add("\"") 78 | /method 79 | 80 | 81 | method txt:Charstash.addDebugLine(fname ptr uint8, line uintptr) 82 | me.add("#line ") 83 | me.addInt(line) 84 | me.add(" \"") 85 | 86 | if fname[0] != 47 87 | mut pwd = proc:getenv("PWD") 88 | 89 | me.add(pwd) 90 | me.add("/") 91 | /if 92 | 93 | me.add(fname) 94 | me.addLine("\"") 95 | /method 96 | 97 | 98 | method txt:Charstash.addPad(p uintptr) 99 | mut i uintptr = 0 100 | 101 | while i < p 102 | me.addChar(32) 103 | 104 | i++ 105 | /while 106 | /method 107 | 108 | 109 | # Operators functions 110 | 111 | func isBinOp(tok uint16) bool 112 | return (tok mod 10) < 2 113 | /func 114 | 115 | 116 | func opConv(tok uint16) ptr uint8 117 | if tok == ast:AMPER or tok == ast:PTR 118 | return "&" 119 | /if 120 | 121 | if tok == ast:AND 122 | return "&&" 123 | /if 124 | 125 | if tok == ast:ASSIGN 126 | return "=" 127 | /if 128 | 129 | if tok == ast:DEC 130 | return "--" 131 | /if 132 | 133 | if tok == ast:DIFFERENT 134 | return "!=" 135 | /if 136 | 137 | if tok == ast:DIV 138 | return "/" 139 | /if 140 | 141 | if tok == ast:EQUAL 142 | return "==" 143 | /if 144 | 145 | if tok == ast:INC 146 | return "++" 147 | /if 148 | 149 | if tok == ast:MAJEQ 150 | return ">=" 151 | /if 152 | 153 | if tok == ast:MAJOR 154 | return ">" 155 | /if 156 | 157 | if tok == ast:MINEQ 158 | return "<=" 159 | /if 160 | 161 | if tok == ast:MINOR 162 | return "<" 163 | /if 164 | 165 | if tok == ast:MINUS or tok == ast:UMINUS 166 | return "-" 167 | /if 168 | 169 | if tok == ast:MOD 170 | return "%" 171 | /if 172 | 173 | if tok == ast:NOT 174 | return "!" 175 | /if 176 | 177 | if tok == ast:OR 178 | return "||" 179 | /if 180 | 181 | if tok == ast:PIPE 182 | return "|" 183 | /if 184 | 185 | if tok == ast:PLUS 186 | return "+" 187 | /if 188 | 189 | if tok == ast:SHIFTL 190 | return "<<" 191 | /if 192 | 193 | if tok == ast:SHIFTR 194 | return ">>" 195 | /if 196 | 197 | if tok == ast:TIMES or tok == ast:VAL 198 | return "*" 199 | /if 200 | 201 | if tok == ast:XOR 202 | return "^" 203 | /if 204 | 205 | tty:errln("UNREACHABLE") 206 | tty:outint(tok) 207 | proc:abort() 208 | 209 | return null 210 | /func 211 | -------------------------------------------------------------------------------- /libctrans/src/ctrans/version.fork: -------------------------------------------------------------------------------- 1 | # libctrans, Fork to C transpiler library 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module ctrans 12 | 13 | 14 | mut RELEASE uint64 = 15 15 | 16 | mut VER_MAJ uint8 = 0 17 | mut VER_MIN uint8 = 7 18 | mut VER_PATCH uint8 = 2 19 | 20 | mut VERSION = "0.7.2" 21 | -------------------------------------------------------------------------------- /libfork/.gitignore: -------------------------------------------------------------------------------- 1 | build/* 2 | perf 3 | examples/old-examples/*.txt 4 | examples/old-examples/*.elf 5 | examples/old-examples/*.old 6 | examples/*.c 7 | examples/parsedir 8 | tests/*.err 9 | core.* 10 | -------------------------------------------------------------------------------- /libfork/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean 2 | 3 | all: clean 4 | $(MAKE) -C src 5 | 6 | transl: 7 | $(MAKE) -C src transl 8 | 9 | clean: 10 | rm -rf build 11 | -------------------------------------------------------------------------------- /libfork/README.md: -------------------------------------------------------------------------------- 1 | libfork 2 | ======= 3 | 4 | A simple implementation of basic routines and data structures for the Fork Language. 5 | 6 | This is incredibly alpha, so it may crash in unpredictable ways. 7 | 8 | Everything is available under the MPL v2 license. 9 | 10 | # Building 11 | 12 | Libfork needs transmod from fork to compile, and it's generally developed in sync with it. 13 | Use a current build of fork to build libfork, or otherwise get it from an official build (see fork releases for more informations). 14 | -------------------------------------------------------------------------------- /libfork/copyright-c.txt: -------------------------------------------------------------------------------- 1 | /* 2 | * libfork, a base library for the Fork language 3 | * Copyright (C) Marco Cilloni 2016 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * Exhibit B is not attached; this software is compatible with the 9 | * licenses expressed under Section 1.12 of the MPL v2. 10 | * 11 | */ 12 | -------------------------------------------------------------------------------- /libfork/copyright-fork.txt: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/aliaxample.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | import ast 12 | import kv 13 | import list 14 | import map 15 | import pair 16 | import parser 17 | import proc 18 | import tty 19 | import utils 20 | 21 | 22 | entry 23 | mut argv = proc:args() 24 | if argv'len != 1 25 | tty:errln("Wrong number of arguments, required: 1") 26 | proc:exit(1) 27 | /if 28 | 29 | mut ctx = parser:new() 30 | mut {ast,issues} = ctx.parseFile(argv'args[0]) 31 | 32 | mut issLen = issues.len() 33 | 34 | if issLen > 0 35 | mut i uintptr = 0 36 | 37 | while i < issLen 38 | mut issue = issues.get(i) 39 | 40 | issue.writeOut(ptr tty:out) 41 | 42 | i++ 43 | /while 44 | 45 | ast:issuesFree(issues) 46 | proc:exit(1) 47 | /if 48 | 49 | ast:issuesFree(issues) 50 | 51 | mut syms = (ast)'aliases'syms 52 | 53 | mut i uintptr = 0 54 | mut len = syms.len() 55 | 56 | while i < len 57 | mut pair = syms.getAt(i) 58 | ast:declDump("alias", (pair'key), (pair'value)) 59 | 60 | i++ 61 | /while 62 | 63 | parser:free(ctx) 64 | 65 | ast:pnodeFree(ast) 66 | /entry 67 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/argxample.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | import args 12 | import tty 13 | 14 | 15 | entry 16 | mut args = args:new("a test application") 17 | 18 | args.newFlag(args:BOOL, "bool", "boolean flag", null, false, false, "--bool", "-b") 19 | args.newFlag(args:STRING, "string", "string flag", "STRING", false, false, "--str", "-s") 20 | args.newFlag(args:LIST, "list", "list flag", "LIST", false, false, "--list", "-L") 21 | args.newFlag(args:STRING, "multi", "multiple flag", "STR", true, false, "--mul", "-m") 22 | args.newFlag(args:STRING, "mand", "mandatory flag", "STR", false, true, "--mand", "-M") 23 | 24 | args.unboundsOpts("UNBOUND", false, true) 25 | 26 | mut err = args.parse() 27 | if err? 28 | tty:err("error: ") 29 | tty:failln(err.msg()) 30 | /if 31 | 32 | tty:out("bool is: ") 33 | tty:outln(args.isSet("bool") => "true" || "false") 34 | 35 | tty:out("string is: ") 36 | mut {ok,string} = args.getStr("string") 37 | tty:outln(ok => string || "") 38 | 39 | tty:out("list is: ") 40 | mut {ok,list} = args.getList("list") 41 | 42 | if ok 43 | tty:out("[") 44 | 45 | mut i uintptr = 0 46 | mut len = list.len() 47 | 48 | while i < len 49 | if i > 0 50 | tty:out(",") 51 | /if 52 | 53 | tty:out(cast(val list.get(i))) 54 | 55 | i++ 56 | /while 57 | 58 | tty:outln("]") 59 | else 60 | tty:outln("") 61 | /if 62 | 63 | tty:out("multi is: ") 64 | mut {ok,multi} = args.getList("multi") 65 | 66 | if ok 67 | tty:out("[") 68 | 69 | mut i uintptr = 0 70 | mut len = multi.len() 71 | 72 | while i < len 73 | if i > 0 74 | tty:out(",") 75 | /if 76 | 77 | tty:out(cast(val multi.get(i))) 78 | 79 | i++ 80 | /while 81 | 82 | tty:outln("]") 83 | else 84 | tty:outln("") 85 | /if 86 | 87 | tty:out("mand is: ") 88 | mut {ok,mand} = args.getStr("mand") 89 | tty:outln(mand) 90 | 91 | tty:out("help is: ") 92 | tty:outln(args'help => "true" || "false") 93 | 94 | tty:out("Unbounds: [") 95 | 96 | mut unb = args.getUnbounds() 97 | mut i uintptr = 0 98 | mut len = unb.len() 99 | 100 | while i < len 101 | if i > 0 102 | tty:out(",") 103 | /if 104 | 105 | tty:out(cast(val unb.get(i))) 106 | 107 | i++ 108 | /while 109 | 110 | tty:outln("]") 111 | 112 | args:free(args) 113 | /entry 114 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/bufxample.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | import buffer 12 | import mem 13 | import tty 14 | 15 | 16 | func dumpBytes(bytes ptr uint8, len uintptr) 17 | mut i uintptr = 0 18 | 19 | while i < len 20 | if i > 0 and (i mod 4) == 0 21 | tty:outln("") 22 | /if 23 | 24 | tty:outint(bytes[i]) 25 | tty:outch(32) 26 | 27 | i++ 28 | /while 29 | /func 30 | 31 | 32 | entry 33 | mut buf = buffer:new(10) 34 | 35 | buf.addByte(90) 36 | 37 | buf.addByte(32) 38 | buf.add("asdf", 4) 39 | buf.prependByte(32) 40 | buf.prepend("qwer", 4) 41 | 42 | mut {bytes,len} = buffer:unwrap(buf) 43 | 44 | dumpBytes(bytes, len) 45 | 46 | mem:free(bytes) 47 | /entry 48 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/callgrind: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | env FORDPATHS="$(dirname $0)/../src/ford/internal/":"$(dirname $0)/../src/ford/" LD_LIBRARY_PATH="$(dirname $0)/../build/" valgrind --tool=callgrind "$(dirname $0)/$1.elf" $2 4 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/cdump: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | env FORDPATHS="$(dirname $0)/../src/ford/internal/":"$(dirname $0)/../src/ford/" LD_LIBRARY_PATH="$(dirname $0)/../build/" lldb -c $2 "$(dirname $0)/$1.elf" 4 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/charxample.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | import cs 12 | import mem 13 | import tty 14 | import txt 15 | 16 | 17 | entry 18 | mut cs = cs:new(10) 19 | mut i uint16 = 0 20 | 21 | while i < 10000 22 | cs.addChar(90) 23 | i++ 24 | /while 25 | 26 | cs.addChar(32) 27 | cs.addInt(150) 28 | cs.addChar(32) 29 | cs.addInt(10000) 30 | 31 | mut len = cs.len() 32 | mut str = cs:unwrap(cs) 33 | 34 | tty:outln(str) 35 | tty:out("strlen == ") 36 | tty:outint(txt:strlen(str)) 37 | tty:outch(10) 38 | tty:out("cslen == ") 39 | tty:outint(len) 40 | tty:outch(10) 41 | 42 | mem:free(str) 43 | /entry 44 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/charxample2.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | import cs 12 | import mem 13 | import tty 14 | import txt 15 | 16 | 17 | entry 18 | mut cs = cs:new(20) 19 | cs.add("This ") 20 | cs.add("actually ") 21 | cs.add("works! ") 22 | 23 | mut str = cs:unwrap(cs) 24 | tty:outln(str) 25 | mem:free(str) 26 | /entry 27 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/charxample3.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | import cs 12 | import mem 13 | import tty 14 | import txt 15 | 16 | 17 | entry 18 | mut cs = cs:new(20) 19 | cs.prepend("works! ") 20 | tty:outln(cs'buf'base) 21 | cs.prepend("actually ") 22 | tty:outln(cs'buf'base) 23 | cs.prepend("This ") 24 | 25 | mut str = cs:unwrap(cs) 26 | tty:outln(str) 27 | mem:free(str) 28 | /entry 29 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/dbg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | env FORDPATHS="$(dirname $0)/../src/ford/internal/":"$(dirname $0)/../src/ford/" LD_LIBRARY_PATH="$(dirname $0)/../build/" lldb "$(dirname $0)/$1.elf" $2 4 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/dynxample.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | import dyn 12 | import err 13 | import proc 14 | import tty 15 | import utils 16 | 17 | 18 | entry 19 | 20 | mut error ptr err:Error 21 | mut libc = dyn:open("/lib/libc.so.6", ptr error) 22 | 23 | if not libc? 24 | tty:err("error: ") 25 | tty:errln(error'msg) 26 | 27 | proc:exit(1) 28 | /if 29 | 30 | mut puts = (libc.sym("puts", ptr error)) 31 | 32 | if not libc? 33 | tty:err("error: ") 34 | tty:errln(error'msg) 35 | 36 | proc:exit(2) 37 | /if 38 | 39 | puts("test") 40 | 41 | dyn:close(libc) 42 | 43 | /entry 44 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/ex: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | env FORDPATHS="$(dirname $0)/../src/ford/internal/":"$(dirname $0)/../src/ford/" LD_LIBRARY_PATH="$(dirname $0)/../build/" "$(dirname $0)/$1.elf" $2 4 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/fordimpxample.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module parser 12 | 13 | 14 | import ast 15 | import cs 16 | import map 17 | import mem 18 | import pair 19 | import parser 20 | import proc 21 | import tty 22 | 23 | 24 | entry 25 | mut argv = proc:args() 26 | if argv'len != 1 27 | tty:errln("Wrong number of arguments, required: 1") 28 | proc:exit(1) 29 | /if 30 | 31 | mut prs = parser:new() 32 | mut {ford,err} = prs.loadFord(argv'args[0]) 33 | 34 | if err? 35 | tty:err("error: ") 36 | tty:failln(err.msg()) 37 | /if 38 | 39 | tty:out("=== MODULE ") 40 | tty:outln(ford'name) 41 | tty:out("\n\n\n") 42 | 43 | tty:out("== IMPORTS: ") 44 | tty:outint(prs'imports.len()) 45 | tty:outch(10) 46 | 47 | mut iter = prs'imports.iter() 48 | 49 | mut pair ptr pair:Pair 50 | 51 | while (pair = iter.next())? 52 | tty:out("Imported ") 53 | tty:outln((pair'key)) 54 | 55 | pair:free(pair) 56 | /while 57 | 58 | map:iterFree(iter) 59 | 60 | mut aliases = ford'aliases'syms 61 | 62 | tty:out("\n\n== ALIASES: ") 63 | tty:outint(aliases.len()) 64 | tty:outch(10) 65 | 66 | mut i uintptr = 0 67 | mut len = aliases.len() 68 | 69 | while i < len 70 | pair = aliases.getAt(i) 71 | tty:out("alias ") 72 | tty:out((pair'key)) 73 | 74 | tty:out(" ") 75 | 76 | mut cs = cs:new(20) 77 | 78 | (pair'value)'type.dump(cs) 79 | 80 | mut txt = cs:unwrap(cs) 81 | 82 | tty:outln(txt) 83 | 84 | mem:free(txt) 85 | i++ 86 | /while 87 | 88 | mut decls = ford'decls'syms 89 | 90 | tty:out("\n\n== DECLS: ") 91 | tty:outint(decls.len()) 92 | tty:outch(10) 93 | 94 | i = 0 95 | len = decls.len() 96 | 97 | while i < len 98 | pair = decls.getAt(i) 99 | mut dinfo = (pair'value) 100 | mut typeStr ptr uint8 = null 101 | 102 | if dinfo'declOnly 103 | tty:out("decl ") 104 | /if 105 | 106 | if dinfo'declType == ast:PFUNCTION 107 | typeStr = "func " 108 | else 109 | if dinfo'declType == ast:PMETHOD 110 | typeStr = "method " 111 | else 112 | typeStr = "mut " 113 | /if 114 | /if 115 | 116 | tty:out(typeStr) 117 | tty:out((pair'key)) 118 | 119 | tty:out(" :: ") 120 | 121 | mut cs = cs:new(10) 122 | dinfo'type.summarize(cs) 123 | 124 | mut des = cs:unwrap(cs) 125 | 126 | tty:outln(des) 127 | 128 | mem:free(des) 129 | 130 | i++ 131 | /while 132 | 133 | tty:out("\n\nEXTRA: ") 134 | if ford'extra? 135 | tty:outln("yes\n\n") 136 | mut os = tty:ttyStream() 137 | 138 | os.write(ford'extra, ford'extraLen) 139 | else 140 | tty:outln("no") 141 | /if 142 | 143 | parser:free(prs) 144 | 145 | parser:fordFree(ford) 146 | /entry 147 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/fordxample.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | import ast 12 | import cs 13 | import fs 14 | import kv 15 | import list 16 | import map 17 | import mem 18 | import pair 19 | import parser 20 | import proc 21 | import tty 22 | import utils 23 | 24 | 25 | entry 26 | mut argv = proc:args() 27 | if argv'len != 1 28 | tty:errln("Wrong number of arguments, required: 1") 29 | proc:exit(1) 30 | /if 31 | 32 | mut prs = parser:new() 33 | mut {pmod,issues} = prs.parseDirectory(argv'args[0]) 34 | 35 | mut issLen = issues.len() 36 | 37 | if issLen > 0 38 | mut i uintptr = 0 39 | 40 | while i < issLen 41 | mut issue = issues.get(i) 42 | 43 | issue.writeOut(ptr tty:out) 44 | 45 | i++ 46 | /while 47 | 48 | ast:issuesFree(issues) 49 | proc:exit(1) 50 | /if 51 | 52 | mut genFord = parser:makeFord(pmod) 53 | 54 | mut err = parser:writeFord(pmod'name, "/tmp", genFord, null, 0) 55 | if err? 56 | tty:failln(err.msg()) 57 | /if 58 | 59 | parser:free(prs) 60 | ast:pmoduleFree(pmod) 61 | /entry 62 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/gdbg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | env FORDPATHS="$(dirname $0)/../src/ford/internal/":"$(dirname $0)/../src/ford/" LD_LIBRARY_PATH="$(dirname $0)/../build/" gdb --args "$(dirname $0)/$1.elf" $2 4 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/hashxample.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | import hash 12 | import tty 13 | 14 | 15 | entry 16 | mut hash = hash:strnew(6) 17 | 18 | hash.put("potato", "battery") 19 | hash.put("honey", "poney") 20 | hash.put("flare", "guaxxa") 21 | hash.put("guagua", "lelzie") 22 | 23 | hash.print() 24 | 25 | tty:out("\nDelete potato: ") 26 | tty:outln(hash.remove("potato") => "OK\n" || "FAILED\n") 27 | 28 | hash.print() 29 | 30 | tty:out("\nDelete tomato: ") 31 | tty:outln(hash.remove("tomato") => "OK\n" || "FAILED\n") 32 | 33 | hash.print() 34 | 35 | tty:outln("\n\nAdd potato again: ") 36 | hash.put("potato", "battery") 37 | 38 | hash.print() 39 | 40 | tty:out("\n\nhash[\"flare\"] == ") 41 | 42 | mut value = (hash.get("flare")) 43 | 44 | tty:outln(value) 45 | 46 | tty:out("hash[\"potato\"] == ") 47 | 48 | value = (hash.get("potato")) 49 | 50 | tty:outln(value) 51 | 52 | hash.put("guagua", "memma") 53 | 54 | hash.print() 55 | 56 | hash:free(hash) 57 | /entry 58 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/hashxample2.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | import hash 12 | import pair 13 | import tty 14 | 15 | 16 | func identHash(item data) uintptr 17 | return (item) 18 | /func 19 | 20 | 21 | func hashIntDump(hash ptr hash:Hash) 22 | tty:out("[ ") 23 | 24 | mut iter = hash.iter() 25 | mut pair ptr pair:Pair = null 26 | mut first = true 27 | 28 | while (pair = iter.next())? 29 | if first 30 | first = false 31 | else 32 | tty:out(", ") 33 | /if 34 | 35 | tty:outint((pair'key)) 36 | tty:out(": ") 37 | tty:outint((pair'value)) 38 | 39 | pair:free(pair) 40 | /while 41 | 42 | hash:iterFree(iter) 43 | 44 | tty:outln(" ]") 45 | /func 46 | 47 | 48 | entry 49 | mut hash = hash:new(6, ptr identHash) 50 | 51 | mut i uintptr = 0 52 | 53 | while i < 30000000 54 | hash.put((i), (i)) 55 | 56 | i++ 57 | /while 58 | 59 | hashIntDump(hash) 60 | 61 | hash:free(hash) 62 | /entry 63 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/kvxample.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | import kv 12 | import mem 13 | import tty 14 | import txt 15 | 16 | 17 | entry 18 | mut kv = kv:strnew(10) 19 | 20 | kv.setFreeFuncs(ptr mem:free, ptr mem:free) 21 | 22 | kv.put(txt:strclone("aaa"), txt:strclone("eee")) 23 | kv.print() 24 | tty:outch(10) 25 | 26 | kv.put(txt:strclone("aaa"), txt:strclone("rrr")) 27 | kv.print() 28 | tty:outch(10) 29 | 30 | kv.put(txt:strclone("ooo"), txt:strclone("uuu")) 31 | kv.print() 32 | tty:outch(10) 33 | 34 | kv.put(txt:strclone("uuu"), txt:strclone("ppp")) 35 | kv.print() 36 | tty:outch(10) 37 | 38 | kv.put(txt:strclone("qwe"), txt:strclone("rere")) 39 | kv.print() 40 | tty:outch(10) 41 | 42 | kv.remove("ooo") 43 | kv.print() 44 | tty:outch(10) 45 | 46 | if kv.contains("qwe") 47 | tty:outln("kv contains \"qwe\"") 48 | /if 49 | 50 | if kv.contains("ooo") 51 | tty:outln("kv contains \"ooo\"") 52 | /if 53 | 54 | kv.put(txt:strclone("qwe"), txt:strclone("zwewe")) 55 | kv.print() 56 | tty:outch(10) 57 | 58 | kv:free(kv) 59 | /entry 60 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/lel.txt: -------------------------------------------------------------------------------- 1 | decl func puts(x ptr uint8) 2 | decl mut x uint8 3 | 4 | entry 5 | x'b.a(c,d)'d.p(22) 6 | /entry 7 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/lexample.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014,2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | import ast 12 | import err 13 | import proc 14 | import tty 15 | 16 | 17 | entry 18 | mut argv = proc:args() 19 | if argv'len != 1 20 | tty:errln("Wrong number of arguments, required: 1") 21 | proc:exit(1) 22 | /if 23 | 24 | mut {lex,err} = ast:lexerNew(val argv'args) 25 | if err? 26 | tty:errln(err.msg()) 27 | proc:exit(1) 28 | /if 29 | 30 | mut tok ptr ast:Token 31 | 32 | while (tok = ast:lexerNext(lex))? 33 | err = ast:lexerError(lex) 34 | if err? 35 | tty:errln(err.msg()) 36 | proc:exit(2) 37 | /if 38 | 39 | tty:out(ast:tokenStr(tok)) 40 | if tok'type == ast:ID or tok'type == ast:STRING 41 | tty:out(": ") 42 | tty:out((tok'value)) 43 | else 44 | if tok'type == ast:NUMBER 45 | tty:out(": ") 46 | tty:outint(tok'value) 47 | /if 48 | /if 49 | 50 | tty:outch(10) 51 | 52 | ast:tokenFree(tok) 53 | /while 54 | 55 | ast:lexerClose(lex) 56 | 57 | /entry 58 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/mapxample2.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | import map 12 | import pair 13 | import tty 14 | 15 | 16 | func numcmp(a,b data) int8 17 | mut x = (a) 18 | mut y = (b) 19 | 20 | return x > y => 1 || (x < y => -1 || 0) 21 | /func 22 | 23 | 24 | func mapIntDump(map ptr map:Map) 25 | tty:out("[ ") 26 | 27 | mut iter = map.iter() 28 | mut pair ptr pair:Pair = null 29 | mut first = true 30 | 31 | while (pair = iter.next())? 32 | if first 33 | first = false 34 | else 35 | tty:out(", ") 36 | /if 37 | 38 | tty:outint((pair'key)) 39 | tty:out(": ") 40 | tty:outint((pair'value)) 41 | 42 | pair:free(pair) 43 | /while 44 | 45 | map:iterFree(iter) 46 | 47 | tty:outln(" ]") 48 | /func 49 | 50 | 51 | entry 52 | mut map = map:new(ptr numcmp) 53 | 54 | mut i uintptr = 0 55 | 56 | while i < 30000000 57 | map.put((i), (i)) 58 | 59 | i++ 60 | /while 61 | 62 | mapIntDump(map) 63 | 64 | map:free(map) 65 | /entry 66 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/massif: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | env FORDPATHS="$(dirname $0)/../src/ford/internal/":"$(dirname $0)/../src/ford/" LD_LIBRARY_PATH="$(dirname $0)/../build/" valgrind --tool=massif --massif-out-file="$PWD/$1.massif" "$(dirname $0)/$1.elf" $2 4 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/memchk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | env FORDPATHS="$(dirname $0)/../src/ford/internal/":"$(dirname $0)/../src/ford/" LD_LIBRARY_PATH="$(dirname $0)/../build/" valgrind --track-origins=yes --leak-check=full "$(dirname $0)/$1.elf" $2 4 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/method.txt: -------------------------------------------------------------------------------- 1 | method txt:String.appendInt(a uint8) bool 2 | 3 | /method 4 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/pathxample.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | import err 12 | import fs 13 | import proc 14 | import tty 15 | 16 | 17 | func pad(p uintptr) 18 | mut i uintptr = 0 19 | 20 | while i < p 21 | tty:out(" ") 22 | 23 | i++ 24 | /while 25 | /func 26 | 27 | 28 | func dirDump(dir ptr fs:Dir, p uintptr) ptr err:Error 29 | tty:out(dir'name) 30 | tty:outln(" {") 31 | 32 | while true 33 | mut {file,err} = dir.next() 34 | if err? 35 | return err 36 | /if 37 | 38 | if not file? 39 | break 40 | /if 41 | 42 | pad(p + 2) 43 | if file.isDir() 44 | {dir,err} = file.openDir() 45 | 46 | fs:fileFree(file) 47 | 48 | if err? 49 | return err 50 | /if 51 | 52 | mut err = dirDump(dir, p + 2) 53 | fs:dirClose(dir) 54 | 55 | if err? 56 | return err 57 | /if 58 | else 59 | tty:outln(file'name) 60 | fs:fileFree(file) 61 | /if 62 | /while 63 | 64 | pad(p) 65 | tty:outln("}") 66 | 67 | return null 68 | /func 69 | 70 | 71 | entry 72 | mut arg = proc:args() 73 | 74 | if arg'len < 1 75 | tty:failln("No arguments given") 76 | /if 77 | 78 | mut {file,err} = fs:stat(arg'args[0]) 79 | if err? 80 | tty:failln(err'msg) 81 | /if 82 | 83 | if not file.isDir() 84 | tty:failln("Argument is not a directory") 85 | /if 86 | 87 | mut {dir,err} = file.openDir() 88 | fs:fileFree(file) 89 | 90 | if err? 91 | tty:failln(err'msg) 92 | /if 93 | 94 | err = dirDump(dir, 0) 95 | 96 | if err? 97 | tty:failln(err'msg) 98 | /if 99 | 100 | fs:dirClose(dir) 101 | /entry 102 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/sdirexample.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | import ast 12 | import parser 13 | import proc 14 | import tty 15 | import utils 16 | 17 | 18 | entry 19 | mut argv = proc:args() 20 | if argv'len != 1 21 | tty:errln("Wrong number of arguments, required: 1") 22 | proc:exit(1) 23 | /if 24 | 25 | mut {pmod,issues} = parser:parseModule(argv'args[0]) 26 | mut len = issues.len() 27 | 28 | if len > 0 29 | mut i uintptr = 0 30 | 31 | while i < len 32 | mut issue = issues.get(i) 33 | 34 | issue.writeOut(ptr tty:err) 35 | 36 | i++ 37 | /while 38 | proc:exit(1) 39 | /if 40 | 41 | pmod.dump() 42 | ast:pmoduleFree(pmod) 43 | ast:issuesFree(issues) 44 | /entry 45 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/semxample.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | import ast 12 | import cs 13 | import kv 14 | import list 15 | import map 16 | import mem 17 | import pair 18 | import parser 19 | import proc 20 | import tty 21 | import utils 22 | 23 | 24 | entry 25 | mut argv = proc:args() 26 | if argv'len != 1 27 | tty:errln("Wrong number of arguments, required: 1") 28 | proc:exit(1) 29 | /if 30 | 31 | mut prs = parser:new() 32 | mut {ast,issues} = prs.parseFile(argv'args[0]) 33 | 34 | mut issLen = issues.len() 35 | 36 | if issLen > 0 37 | mut i uintptr = 0 38 | 39 | while i < issLen 40 | mut issue = issues.get(i) 41 | 42 | issue.writeOut(ptr tty:out) 43 | 44 | i++ 45 | /while 46 | 47 | ast:issuesFree(issues) 48 | proc:exit(1) 49 | /if 50 | 51 | mut root = (ast) 52 | 53 | tty:out("== IMPORTS: ") 54 | tty:outint(prs'imports.len()) 55 | tty:outch(10) 56 | 57 | mut iter = prs'imports.iter() 58 | 59 | mut pair ptr pair:Pair 60 | 61 | while (pair = iter.next())? 62 | tty:out("Imported ") 63 | tty:outln((pair'key)) 64 | 65 | pair:free(pair) 66 | /while 67 | 68 | map:iterFree(iter) 69 | 70 | mut aliases = (ast)'aliases'syms 71 | 72 | tty:out("\n\n== ALIASES: ") 73 | tty:outint(aliases.len()) 74 | tty:outch(10) 75 | 76 | mut i uintptr = 0 77 | mut len = aliases.len() 78 | 79 | while i < len 80 | pair = aliases.getAt(i) 81 | tty:out("alias ") 82 | tty:outln((pair'key)) 83 | 84 | i++ 85 | /while 86 | 87 | mut decls = (ast)'node'syms'syms 88 | 89 | tty:out("\n\n== DECLS: ") 90 | tty:outint(decls.len()) 91 | tty:outch(10) 92 | 93 | i = 0 94 | len = decls.len() 95 | 96 | while i < len 97 | pair = decls.getAt(i) 98 | mut dinfo = (pair'value) 99 | mut typeStr ptr uint8 = null 100 | 101 | if dinfo'declOnly 102 | tty:out("decl ") 103 | /if 104 | 105 | if dinfo'declType == ast:PFUNCTION 106 | typeStr = "func " 107 | else 108 | if dinfo'declType == ast:PENTRY 109 | typeStr = "entry " 110 | else 111 | if dinfo'declType == ast:PMETHOD 112 | typeStr = "method " 113 | else 114 | typeStr = "mut " 115 | /if 116 | /if 117 | /if 118 | 119 | tty:out(typeStr) 120 | tty:out((pair'key)) 121 | 122 | tty:out(" :: ") 123 | 124 | mut cs = cs:new(10) 125 | dinfo'type.summarize(cs) 126 | 127 | mut des = cs:unwrap(cs) 128 | 129 | tty:outln(des) 130 | 131 | mem:free(des) 132 | 133 | i++ 134 | /while 135 | 136 | tty:out("\n\n==> Has entry? ") 137 | 138 | tty:outln(root'entryNode? => "yes" || "no") 139 | 140 | parser:free(prs) 141 | 142 | ast:pnodeFree(ast) 143 | /entry 144 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/sexample.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014,2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | import ast 12 | import parser 13 | import proc 14 | import tty 15 | import utils 16 | 17 | 18 | entry 19 | mut argv = proc:args() 20 | if argv'len != 1 21 | tty:errln("Wrong number of arguments, required: 1") 22 | proc:exit(1) 23 | /if 24 | 25 | mut {file,err} = parser:parse(argv'args[0]) 26 | 27 | if err? 28 | err.writeOut(ptr tty:err) 29 | proc:exit(1) 30 | /if 31 | 32 | file.dump() 33 | ast:pnodeFree(file) 34 | /entry 35 | -------------------------------------------------------------------------------- /libfork/examples/old-examples/splitxample.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | import mem 12 | import tty 13 | import txt 14 | 15 | 16 | entry 17 | 18 | mut tkz = txt:tokenizerNew("/home/marco/Workspace/forklift/second-step/examples/../src/ford/internal/:/home/marco/Workspace/forklift/second-step/examples/../../first-step/build/libfork/ford/internal/", 58) 19 | 20 | mut nxt ptr uint8 21 | 22 | while (nxt = tkz.next())? 23 | tty:outln(nxt) 24 | mem:free(nxt) 25 | /while 26 | 27 | txt:tokenizerFree(tkz) 28 | /entry 29 | -------------------------------------------------------------------------------- /libfork/src/Makefile: -------------------------------------------------------------------------------- 1 | BUILD = $(shell pwd)/../build/ 2 | CFILES = $(BUILD)/cfiles/libfork/ 3 | FORDS = $(BUILD)/ford/ 4 | 5 | CFLAGS = -Wno-incompatible-pointer-types -Wno-implicit-function-declaration -Wno-incompatible-function-pointer-types -w -g -std=c99 -D_POSIX_C_SOURCE=200112L 6 | 7 | ifndef TRNS 8 | TRNS = transmod 9 | endif 10 | 11 | TRNSCMD = env FORDPATHS=$(FORDS) $(TRNS) -fo $(FORDS) -co $(CFILES) 12 | 13 | ifndef AR 14 | AR=ar 15 | endif 16 | 17 | ifndef RANLIB 18 | RANLIB=ranlib 19 | endif 20 | 21 | MACHINE = $(shell uname -m) 22 | 23 | ifeq ($(MACHINE), amd64) 24 | AMD64 = yes 25 | endif 26 | 27 | ifdef AMD64 28 | ifeq (,$(findstring CYGWIN,$(UNAME))) 29 | FPIC = -fPIC 30 | endif 31 | endif 32 | 33 | SONAME = 'libfork.so' 34 | ARNAME = 'libfork.a' 35 | 36 | .PHONY: all clean 37 | 38 | all: 39 | $(MAKE) transl 40 | $(MAKE) cc-ar 41 | 42 | transl: 43 | mkdir -p $(BUILD) 44 | mkdir -p $(FORDS) 45 | mkdir -p $(CFILES) 46 | find $(shell pwd) -name '*.c' -exec cp {} $(CFILES) \; 47 | $(TRNSCMD) about 48 | $(TRNSCMD) c 49 | $(TRNSCMD) math 50 | $(TRNSCMD) proc 51 | $(TRNSCMD) -n rt rt 52 | $(TRNSCMD) mem 53 | $(TRNSCMD) tty 54 | $(TRNSCMD) txt 55 | $(TRNSCMD) sort 56 | $(TRNSCMD) err 57 | $(TRNSCMD) io 58 | $(TRNSCMD) pair 59 | $(TRNSCMD) vect 60 | $(TRNSCMD) list 61 | $(TRNSCMD) map 62 | $(TRNSCMD) hash 63 | $(TRNSCMD) set 64 | $(TRNSCMD) kv 65 | $(TRNSCMD) fs 66 | $(TRNSCMD) dyn 67 | $(TRNSCMD) misc 68 | $(TRNSCMD) memutils 69 | $(TRNSCMD) args 70 | mv $(CFILES)/rt.c $(CFILES)/.. 71 | 72 | cc-ar: 73 | cd $(CFILES) && $(CC) -c $(CFLAGS) $(CFILES)/*.c 74 | $(CC) $(CFLAGS) -c -o $(BUILD)/rt.o $(CFILES)/../rt.c 75 | @printf "AR\t\t%s\n" $(ARNAME) 76 | @ $(AR) rc $(BUILD)/$(ARNAME) $(CFILES)/*.o 77 | @ $(RANLIB) $(BUILD)/$(ARNAME) 78 | 79 | clean: 80 | rm -rf $(BUILD) 81 | -------------------------------------------------------------------------------- /libfork/src/about/version.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module about 12 | 13 | 14 | mut RELEASE uint16 = 13 15 | 16 | mut VER_MAJ uint8 = 0 17 | mut VER_MIN uint8 = 7 18 | mut VER_PATCH uint8 = 2 19 | 20 | mut VERSION = "0.7.2" 21 | 22 | 23 | #mut ptrSize uint8 = 4 24 | mut ptrSize uint8 = 8 25 | -------------------------------------------------------------------------------- /libfork/src/c/c.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | module c 11 | 12 | alias cuchar uint8 13 | alias cushort uint16 14 | alias cuint uint32 15 | alias culong uint64 16 | alias culonglong uint64 17 | 18 | alias cchar int8 19 | alias cshort int16 20 | alias cint int32 21 | alias clong int64 22 | alias clonglong int64 23 | 24 | alias csizet uintptr 25 | 26 | alias CFILE data 27 | 28 | 29 | # libc std streams wrapper functions 30 | func stderr_file() CFILE 31 | decl func stderr_file() CFILE 32 | 33 | return stderr_file() 34 | /func 35 | 36 | 37 | func stdin_file() CFILE 38 | decl func stdin_file() CFILE 39 | 40 | return stdin_file() 41 | /func 42 | 43 | 44 | func stdout_file() CFILE 45 | decl func stdout_file() CFILE 46 | 47 | return stdout_file() 48 | /func 49 | -------------------------------------------------------------------------------- /libfork/src/c/cstreams.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libfork, a base library for the Fork language 3 | * Copyright (C) Marco Cilloni 2014, 2015, 2016 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * Exhibit B is not attached; this software is compatible with the 9 | * licenses expressed under Section 1.12 of the MPL v2. 10 | * 11 | */ 12 | 13 | #include 14 | #include 15 | 16 | FILE* stderr_file(void) { 17 | return stderr; 18 | } 19 | 20 | FILE* stdin_file(void) { 21 | return stdin; 22 | } 23 | 24 | FILE* stdout_file(void) { 25 | return stdout; 26 | } 27 | -------------------------------------------------------------------------------- /libfork/src/dyn/dyn.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module dyn 12 | 13 | 14 | import err 15 | import mem 16 | import txt 17 | 18 | 19 | alias SObj struct( 20 | handl data, 21 | name ptr uint8 22 | ) 23 | 24 | 25 | decl func load_lib(name ptr uint8, err ptr uint8, len uintptr) data 26 | decl func load_sym(handl data, name ptr uint8, err ptr uint8, len uintptr) data 27 | decl func free_lib(handl data, err ptr uint8, len uintptr) bool 28 | 29 | 30 | func close(sobj ptr SObj) 31 | mut buf [1024] uint8 # ignore the error, though, I don't care about it right now 32 | 33 | free_lib(sobj'handl, ptr buf[0], 1024) 34 | mem:free(sobj) 35 | /func 36 | 37 | 38 | func open(name ptr uint8, err ptr ptr err:Error) ptr SObj 39 | mut ret = (mem:alloc(size(SObj))) 40 | 41 | if not sobjInit(ret, name, err) 42 | mem:free(ret) 43 | 44 | return null 45 | /if 46 | 47 | return ret 48 | /func 49 | 50 | 51 | func sobjInit(sobj ptr SObj, name ptr uint8, err ptr ptr err:Error) bool 52 | mut buf [1024] uint8 53 | sobj'handl = load_lib(name, ptr buf[0], 1024) 54 | 55 | if not sobj'handl? 56 | val err = err:new(ptr buf[0]) 57 | 58 | return false 59 | /if 60 | 61 | sobj'name = txt:strclone(name) 62 | 63 | return true 64 | /func 65 | 66 | 67 | method SObj.sym(name ptr uint8, err ptr ptr err:Error) data 68 | mut buf [1024] uint8 69 | 70 | mut sym = load_sym(me'handl, name, ptr buf[0], 1024) 71 | if not sym? 72 | val err = err:new(ptr buf[0]) 73 | 74 | return null 75 | /if 76 | 77 | return sym 78 | /method 79 | 80 | 81 | #mut SO_SUFFIX = ".dylib" 82 | #mut SO_SUFFIX = ".dll" 83 | mut SO_SUFFIX = ".so" 84 | -------------------------------------------------------------------------------- /libfork/src/dyn/loadlib.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libfork, a base library for the Fork language 3 | * Copyright (C) Marco Cilloni 2015, 2016 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * Exhibit B is not attached; this software is compatible with the 9 | * licenses expressed under Section 1.12 of the MPL v2. 10 | * 11 | */ 12 | 13 | 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | 21 | void* load_lib(uint8_t *name, uint8_t* err, uintptr_t len) { 22 | void* handl = dlopen((char*) name, RTLD_LAZY); //improve this 23 | 24 | if (handl == NULL) { 25 | strncpy((char*) err, dlerror(), len); 26 | err[len - 1] = '\0'; 27 | 28 | return NULL; 29 | } 30 | 31 | return handl; 32 | } 33 | 34 | 35 | void* load_sym(void* handl, uint8_t* name, uint8_t* err, uintptr_t len) { 36 | dlerror(); //discard old errors 37 | 38 | void* sym = dlsym(handl, (char*) name); 39 | 40 | char* dlErr = dlerror(); 41 | 42 | if (dlErr != NULL) { 43 | strncpy((char*) err, dlErr, len); 44 | err[len - 1] = '\0'; 45 | 46 | return NULL; 47 | } 48 | 49 | return sym; 50 | } 51 | 52 | 53 | bool free_lib(void* handl, uint8_t* err, uintptr_t len) { 54 | if (dlclose(handl) != 0) { 55 | strncpy((char*) err, dlerror(), len); 56 | err[len - 1] = '\0'; 57 | 58 | return false; 59 | } 60 | 61 | return true; 62 | } 63 | -------------------------------------------------------------------------------- /libfork/src/err/error.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module err 12 | 13 | 14 | import mem 15 | import txt 16 | 17 | 18 | # error structure 19 | alias Error struct ( 20 | msg ptr uint8 21 | ) 22 | 23 | 24 | func free(err ptr Error) 25 | if err? 26 | mem:free(err'msg) 27 | mem:free(err) 28 | /if 29 | /func 30 | 31 | 32 | func glue(strs ptr ptr uint8) ptr Error 33 | mut err = (mem:alloc(size(Error))) 34 | err'msg = txt:strglue(strs) 35 | return err 36 | /func 37 | 38 | 39 | func new(str ptr uint8) ptr Error 40 | mut err = (mem:alloc(size(Error))) 41 | err'msg = txt:strclone(str) 42 | return err 43 | /func 44 | 45 | 46 | method Error.msg() ptr uint8 47 | return me'msg 48 | /method 49 | -------------------------------------------------------------------------------- /libfork/src/fs/dir.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module fs 12 | 13 | 14 | import err 15 | import mem 16 | import txt 17 | 18 | 19 | alias Dir struct( 20 | absPath,name ptr uint8, 21 | internal data 22 | ) 23 | 24 | 25 | decl func dir_close(dirp data) 26 | decl func dir_next(dirp data, openPath ptr uint8, end ptr bool, 27 | error ptr uint8, errl uintptr) ptr uint8 28 | 29 | decl func dir_open(path,error ptr uint8, errl uintptr) data 30 | 31 | 32 | func dir(name ptr uint8) {dir ptr Dir, err ptr err:Error} 33 | mut buf [512] uint8 34 | 35 | mut dirp = dir_open(name, ptr buf[0], 512) 36 | if not dirp? 37 | return {null, err:new(ptr buf[0])} 38 | /if 39 | 40 | mut ret = (mem:alloc(size(Dir))) 41 | 42 | ret'name = txt:strclone(pathBasename(name)) 43 | ret'absPath = pathAbsolute(name) 44 | ret'internal = dirp 45 | 46 | return {ret, null} 47 | /func 48 | 49 | 50 | func dirClose(dirp ptr Dir) 51 | dir_close(dirp'internal) 52 | mem:free(dirp'name) 53 | mem:free(dirp'absPath) 54 | 55 | mem:free(dirp) 56 | /func 57 | 58 | 59 | method Dir.next() {file ptr File, err ptr err:Error} 60 | mut end = false 61 | mut buf [512] uint8 62 | 63 | mut name = dir_next(me'internal, me'absPath, ptr end, ptr buf[0], 512) 64 | if not name? 65 | if end 66 | return {null, null} 67 | /if 68 | 69 | return {null, err:new(ptr buf[0])} 70 | /if 71 | 72 | mut glued = pathJoin(me'absPath, name) 73 | 74 | mut ret = stat(glued) 75 | 76 | mem:free(glued) 77 | 78 | return ret 79 | /method 80 | -------------------------------------------------------------------------------- /libfork/src/fs/file.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module fs 12 | 13 | 14 | import err 15 | import io 16 | import mem 17 | 18 | 19 | alias File struct( 20 | name,path ptr uint8, 21 | isDir bool, 22 | length uint64 23 | ) 24 | 25 | 26 | func filereadInternal(camoFd data, bytes ptr uint8, len intptr, err ptr ptr err:Error, eof ptr bool) uintptr 27 | mut fd = (camoFd) 28 | decl func stream_readfileInternal(fd int64, buf data, len intptr, error ptr uint8, errLen uintptr) intptr 29 | mut buf [512] uint8 30 | mut rd = stream_readfileInternal(fd, bytes, len, ptr buf[0], 512) 31 | 32 | if rd < 0 33 | val err = err:new(ptr buf[0]) 34 | return 0 35 | /if 36 | 37 | if rd == 0 38 | val eof = true 39 | /if 40 | 41 | return rd 42 | /func 43 | 44 | 45 | func filewriteInternal(camoFd data, bytes ptr uint8, len intptr, err ptr ptr err:Error) uintptr 46 | mut fd = (camoFd) 47 | decl func stream_writefileInternal(fd int64, buf data, len intptr, error ptr uint8, errLen uintptr) intptr 48 | mut buf [512] uint8 49 | mut wt intptr 50 | mut wttot intptr = 0 51 | 52 | while wttot < len 53 | wt = stream_writefileInternal(fd, bytes + wttot, len - wttot, ptr buf[0], 512) 54 | 55 | if wt < 0 56 | val err = err:new(ptr buf[0]) 57 | return 0 58 | /if 59 | 60 | wttot = wttot + wt 61 | /while 62 | 63 | return wttot 64 | /func 65 | 66 | 67 | func filecloseInternal(camoFd data, err ptr ptr err:Error) bool 68 | decl func stream_closefileInternal(fd int64, error ptr uint8, errLen uintptr) uint8 69 | mut buf [512] uint8 70 | 71 | if stream_closefileInternal((camoFd), ptr buf[0], 512) != 0 72 | return true 73 | /if 74 | 75 | return false 76 | /func 77 | 78 | 79 | func fileFree(fi ptr File) 80 | if fi? 81 | mem:free(fi'path) 82 | mem:free(fi) 83 | /if 84 | /func 85 | 86 | 87 | func stat(filename ptr uint8) {file ptr File, err ptr err:Error} 88 | decl func file_populate(filename,error ptr uint8, errl uintptr) ptr File 89 | 90 | mut buf [512] uint8 91 | 92 | mut ret = file_populate(filename, ptr buf[0], 512) 93 | if not ret? 94 | return {null, err:new(ptr buf[0])} 95 | /if 96 | 97 | return {ret, null} 98 | /func 99 | 100 | 101 | method File.isDir() bool 102 | return me'isDir 103 | /method 104 | 105 | 106 | method File.len() uint64 107 | return me'length 108 | /method 109 | 110 | 111 | method File.open() {stream ptr io:Stream, err ptr err:Error} 112 | return fileOpen(me'path) 113 | /method 114 | 115 | 116 | method File.openDir() {dir ptr Dir, err ptr err:Error} 117 | return dir(me'path) 118 | /method 119 | 120 | 121 | method File.path() ptr uint8 122 | return me'path 123 | /method 124 | 125 | 126 | func fileOpen(filename ptr uint8) {stream ptr io:Stream, err ptr err:Error} 127 | decl func open_readfile(name ptr uint8, error ptr uint8, errlen uintptr) int64 128 | mut buf [512] uint8 129 | 130 | mut fd = open_readfile(filename, ptr buf[0], 512) 131 | if fd < 0 132 | return {null, err:new(ptr buf[0])} 133 | /if 134 | 135 | return {io:streamNew((fd), ptr filereadInternal, \ 136 | null, ptr filecloseInternal), null} 137 | /func 138 | 139 | 140 | func fileCreate(filename ptr uint8) {stream ptr io:Stream, err ptr err:Error} 141 | decl func open_writefile(name ptr uint8, error ptr uint8, errlen uintptr) int64 142 | mut buf [512] uint8 143 | 144 | mut fd = open_writefile(filename, ptr buf[0], 512) 145 | if fd < 0 146 | return {null, err:new(ptr buf[0])} 147 | /if 148 | 149 | return {io:streamNew((fd), null, ptr filewriteInternal, \ 150 | ptr filecloseInternal), null} 151 | /func 152 | -------------------------------------------------------------------------------- /libfork/src/fs/filefcn.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libfork, a base library for the Fork language 3 | * Copyright (C) Marco Cilloni 2014, 2015, 2016 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * Exhibit B is not attached; this software is compatible with the 9 | * licenses expressed under Section 1.12 of the MPL v2. 10 | * 11 | */ 12 | 13 | #undef _GNU_SOURCE 14 | #define _XOPEN_SOURCE 15 | #define _XOPEN_SOURCE_EXTENDED 16 | 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | 31 | 32 | int64_t open_readfile(char* filename, char* error, uintptr_t len) { 33 | int64_t fd = open(filename, O_RDONLY); 34 | 35 | if (fd < 0) { 36 | strerror_r(errno, error, len); 37 | return -1; 38 | } 39 | 40 | return fd; 41 | } 42 | 43 | 44 | int64_t open_writefile(char* filename, char* error, uintptr_t len) { 45 | int64_t fd = creat(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 46 | 47 | if (fd < 0) { 48 | strerror_r(errno, error, len); 49 | return -1; 50 | } 51 | 52 | return fd; 53 | } 54 | 55 | 56 | uint8_t stream_closefileInternal(int64_t fd, char* error, uintptr_t len) { 57 | int res = close(fd); 58 | 59 | if (res == -1) { 60 | strerror_r(errno, error, len); 61 | return 0; 62 | } 63 | 64 | return 1; 65 | } 66 | 67 | 68 | intptr_t stream_readfileInternal(int64_t fd, void* data, intptr_t len, char* error, uintptr_t errl) { 69 | intptr_t res = read(fd, data, len); 70 | 71 | if (res < 0) { 72 | strerror_r(errno, error, errl); 73 | return -1; 74 | } 75 | 76 | return res; 77 | } 78 | 79 | 80 | intptr_t stream_writefileInternal(int64_t fd, void* data, intptr_t len, char* error, uintptr_t errl) { 81 | intptr_t res = write(fd, data, len); 82 | 83 | if (res < 0) { 84 | strerror_r(errno, error, errl); 85 | return -1; 86 | } 87 | 88 | return res; 89 | } 90 | 91 | 92 | int8_t stream_closeFileInternal(int64_t fd) { 93 | return close(fd) == 0; 94 | } 95 | 96 | 97 | struct File { 98 | uint8_t* name; 99 | uint8_t* path; 100 | bool isDir; 101 | uint64_t length; 102 | }; 103 | 104 | 105 | struct File* file_populate(char* path, char* error, uintptr_t errl) { 106 | struct stat st; 107 | 108 | if (stat(path, &st)) { 109 | strerror_r(errno, error, errl); 110 | return NULL; 111 | } 112 | 113 | 114 | struct File* fi = malloc(sizeof(struct File)); 115 | 116 | fi->name = strdup(basename(path)); 117 | fi->path = realpath(path, NULL); 118 | fi->isDir = S_ISDIR(st.st_mode) != 0; 119 | fi->length = (uint64_t) st.st_size; 120 | 121 | return fi; 122 | } 123 | 124 | 125 | char* path_absolute(char *relPath) { 126 | return realpath(relPath, NULL); 127 | } 128 | 129 | 130 | uintptr_t path_exists(char* filename) { 131 | struct stat st; 132 | 133 | if (!stat(filename, &st)) { 134 | if (S_ISDIR(st.st_mode)) { 135 | return 2U; 136 | } 137 | 138 | return 1U; 139 | } 140 | 141 | return 0U; 142 | } 143 | 144 | 145 | void dir_close(DIR* dir) { 146 | closedir(dir); 147 | } 148 | 149 | 150 | char* dir_next(DIR* dirp, char *openPath, bool* end, char* error, uintptr_t errl) { 151 | 152 | struct dirent entry, *result; 153 | 154 | int failure = readdir_r(dirp, &entry, &result); 155 | if (failure) { 156 | strerror_r(errno, error, errl); 157 | *end = false; 158 | return NULL; 159 | } 160 | 161 | if ((*end = !result)) { 162 | return NULL; 163 | } 164 | 165 | if (!strcmp(entry.d_name, ".") || !strcmp(entry.d_name, "..")) { 166 | return dir_next(dirp, openPath, end, error, errl); 167 | } 168 | 169 | return strdup(entry.d_name); 170 | } 171 | 172 | 173 | 174 | void* dir_open(char* path, char* error, uintptr_t errl) { 175 | DIR* dp = opendir(path); 176 | if (!dp) { 177 | strerror_r(errno, error, errl); 178 | return NULL; 179 | } 180 | 181 | return dp; 182 | } 183 | 184 | 185 | bool path_listAll(char* path, void* appendTo, void (*appender)(void* to, char* elem), char* error, uintptr_t errl) { 186 | DIR* dp = opendir(path); 187 | if (!dp) { 188 | strerror_r(errno, error, errl); 189 | return false; 190 | } 191 | 192 | struct dirent *ep; 193 | 194 | while ((ep = readdir(dp))) { 195 | char* name = strdup(ep->d_name); 196 | 197 | if (strcmp(name, ".") && strcmp(name, "..")) { 198 | appender(appendTo, name); 199 | } else { 200 | free(name); 201 | } 202 | 203 | } 204 | 205 | closedir(dp); 206 | 207 | return true; 208 | } 209 | -------------------------------------------------------------------------------- /libfork/src/fs/lineno.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module fs 12 | 13 | 14 | import mem 15 | import txt 16 | 17 | 18 | alias Lineno struct( 19 | filename ptr uint8, 20 | lineno,pos uintptr 21 | ) 22 | 23 | 24 | func linenoClone(lineno ptr Lineno) ptr Lineno 25 | return linenoNew(txt:strclone(lineno'filename), lineno'lineno, lineno'pos) 26 | /func 27 | 28 | 29 | func linenoFree(lineno ptr Lineno) 30 | if lineno? 31 | mem:free(lineno'filename) 32 | mem:free(lineno) 33 | /if 34 | /func 35 | 36 | 37 | func linenoNew(filename ptr uint8, lineno, pos uintptr) ptr Lineno 38 | mut ret = (mem:alloc(size(Lineno))) 39 | 40 | ret'filename = filename 41 | ret'lineno = lineno 42 | ret'pos = pos 43 | 44 | return ret 45 | /func 46 | -------------------------------------------------------------------------------- /libfork/src/fs/paths.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module fs 12 | 13 | 14 | import err 15 | import list 16 | import mem 17 | import txt 18 | 19 | 20 | mut dirSep = "/" 21 | 22 | 23 | decl func path_absolute(relPath ptr uint8) ptr uint8 24 | 25 | 26 | decl func path_exists(path ptr uint8) uintptr 27 | 28 | decl func path_listAll(path ptr uint8, 29 | appendTo data, 30 | appender ptr func(to data, elem ptr uint8), 31 | error ptr uint8, 32 | errl uintptr) bool 33 | 34 | 35 | 36 | # path functions 37 | func pathAbsolute(relPath ptr uint8) ptr uint8 38 | return path_absolute(relPath) 39 | /func 40 | 41 | 42 | func pathExists(path ptr uint8) bool 43 | mut result = path_exists(path) 44 | 45 | return result != 0 46 | /func 47 | 48 | 49 | func pathExistsDir(path ptr uint8) bool 50 | mut result = path_exists(path) 51 | 52 | return result == 2 53 | /func 54 | 55 | 56 | func pathJoin(path1,path2 ptr uint8) ptr uint8 57 | mut arr [4] ptr uint8 58 | 59 | arr[0] = path1 60 | arr[1] = dirSep 61 | arr[2] = path2 62 | arr[3] = null 63 | 64 | return txt:strglue(ptr arr[0]) 65 | /func 66 | 67 | 68 | func pathContains(path,filename ptr uint8) bool 69 | mut fullpath = pathJoin(path, filename) 70 | 71 | mut ret = pathExists(fullpath) 72 | 73 | mem:free(fullpath) 74 | 75 | return ret 76 | /func 77 | 78 | 79 | func listAppend(to data, elem ptr uint8) 80 | (to).append(elem) 81 | /func 82 | 83 | 84 | func pathListFiles(path ptr uint8) {paths ptr list:List, err ptr err:Error} 85 | mut ret = list:new() 86 | mut buf [512] uint8 87 | 88 | if not path_listAll(path, ret, ptr listAppend, ptr buf[0], 512) 89 | list:free(ret) 90 | 91 | return {null, err:new(ptr buf[0])} 92 | /if 93 | 94 | return {ret, null} 95 | /func 96 | 97 | 98 | func pathBasename(path ptr uint8) ptr uint8 99 | decl func basename(path ptr uint8) ptr uint8 100 | 101 | return basename(path) 102 | /func 103 | -------------------------------------------------------------------------------- /libfork/src/hash/hash.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module hash 12 | 13 | 14 | import list 15 | import mem 16 | import pair 17 | import tty 18 | import txt 19 | import vect 20 | 21 | 22 | alias Entry struct( 23 | hash uintptr, 24 | key,value data 25 | ) 26 | 27 | 28 | alias Hash struct( 29 | buckets ptr vect:Vect, 30 | hf hashfn, 31 | len uintptr, 32 | freeKey,freeVal ptr func(item data) 33 | ) 34 | 35 | 36 | # entry init/deinit functions 37 | 38 | func entryDeinit(ent ptr Entry, hash ptr Hash) 39 | if hash'freeKey? 40 | hash'freeKey(ent'key) 41 | /if 42 | 43 | if hash'freeVal? 44 | hash'freeVal(ent'value) 45 | /if 46 | /func 47 | 48 | 49 | func entryNew(hash uintptr, key,value data) ptr Entry 50 | mut ent = (mem:alloc(size(Entry))) 51 | 52 | ent'hash = hash 53 | ent'key = key 54 | ent'value = value 55 | 56 | return ent 57 | /func 58 | 59 | 60 | # hash init/deinit functions 61 | 62 | func deinit(hash ptr Hash) 63 | mut i uintptr = 0 64 | mut len = hash'buckets.len() 65 | 66 | while i < len 67 | mut bucket = (val hash'buckets.get(i)) 68 | 69 | if bucket? 70 | mut j uintptr = 0 71 | mut bucketLen = bucket.len() 72 | 73 | while j < bucketLen 74 | mut item = (val bucket.get(j)) 75 | 76 | entryDeinit(item, hash) 77 | mem:free(item) 78 | 79 | j++ 80 | /while 81 | 82 | list:free(bucket) 83 | /if 84 | 85 | i++ 86 | /while 87 | 88 | vect:free(hash'buckets) 89 | /func 90 | 91 | 92 | func free(hash ptr Hash) 93 | if hash? 94 | deinit(hash) 95 | mem:free(hash) 96 | /if 97 | /func 98 | 99 | 100 | func init(hash ptr Hash, cap uintptr, hf hashfn) ptr Hash 101 | mem:set(hash, 0, size(Hash)) 102 | 103 | hash'buckets = vect:new(cap) 104 | hash'hf = hf 105 | 106 | return hash 107 | /func 108 | 109 | 110 | func new(cap uintptr, hf hashfn) ptr Hash 111 | return init((mem:alloc(size(Hash))), cap, hf) 112 | /func 113 | 114 | 115 | # hash methods 116 | 117 | method Hash.clone() ptr Hash 118 | mut newHash = new(me'buckets'cap, me'hf) 119 | 120 | mut hiter = me.iter() 121 | 122 | mut pair ptr pair:Pair = null 123 | 124 | while (pair = hiter.next())? 125 | newHash.put(pair'key, pair'value) 126 | 127 | pair:free(pair) 128 | /while 129 | 130 | iterFree(hiter) 131 | 132 | return newHash 133 | /method 134 | 135 | 136 | method Hash.contains(key data) bool 137 | mut discard data 138 | return me.getInternal(key, ptr discard) 139 | /method 140 | 141 | 142 | method Hash.get(key data) data 143 | mut discard data = null 144 | me.getInternal(key, ptr discard) 145 | 146 | return discard 147 | /method 148 | 149 | 150 | method Hash.getInternal(key data, value ptr data) bool 151 | mut keyHash = me'hf(key) 152 | mut bucketCap = me'buckets.cap() 153 | 154 | if bucketCap == 0 155 | return false 156 | /if 157 | 158 | mut buckAddr = me'buckets.get(keyHash mod bucketCap) 159 | 160 | if not buckAddr? 161 | return false 162 | /if 163 | 164 | mut bucket = (val buckAddr) 165 | 166 | if bucket? 167 | mut entLen = bucket.len() 168 | mut i uintptr = 0 169 | 170 | while i < entLen 171 | mut ent = (val bucket.get(i)) 172 | 173 | if ent'hash == keyHash 174 | val value = ent'value 175 | 176 | return true 177 | /if 178 | 179 | i++ 180 | /while 181 | /if 182 | 183 | val value = null 184 | return false 185 | /method 186 | 187 | 188 | method Hash.len() uintptr 189 | return me'len 190 | /method 191 | 192 | 193 | # the load factor is expressed as a percentage, because there are no floating point 194 | # numbers at the moment. 195 | method Hash.loadFactor() uint8 196 | mut buckNum = me'buckets.cap() 197 | 198 | if buckNum == 0 199 | return 0 200 | /if 201 | 202 | return ((me.len() * 100) / buckNum) 203 | /method 204 | 205 | 206 | method Hash.print() 207 | # TODO: complete 208 | 209 | tty:out("[ ") 210 | 211 | mut hiter = me.iter() 212 | 213 | mut pair ptr pair:Pair = null 214 | mut first = true 215 | 216 | while (pair = hiter.next())? 217 | if first 218 | first = false 219 | else 220 | tty:out(", ") 221 | /if 222 | 223 | tty:out((pair'key)) 224 | tty:out(": ") 225 | tty:out((pair'value)) 226 | 227 | pair:free(pair) 228 | /while 229 | 230 | iterFree(hiter) 231 | 232 | tty:out(" ]") 233 | /method 234 | 235 | 236 | method Hash.put(key data, value data) 237 | 238 | # if the load factor is above or equal 75%, then the hash must be resized. 239 | if me.loadFactor() >= 75 240 | me.rehash() 241 | /if 242 | 243 | mut keyHash = me'hf(key) 244 | mut bucketsNum = me'buckets.cap() 245 | mut index = keyHash mod bucketsNum 246 | 247 | mut buckAddr = me'buckets.get(index) 248 | mut bucket ptr list:List = null 249 | mut exists = false 250 | 251 | if not buckAddr? 252 | bucket = list:new() 253 | me'buckets.put(index, bucket) 254 | else 255 | bucket = (val buckAddr) 256 | 257 | if not bucket? 258 | bucket = list:new() 259 | me'buckets.put(index, bucket) 260 | /if 261 | /if 262 | 263 | mut buckLen = bucket.len() 264 | mut i uintptr = 0 265 | 266 | while i < buckLen 267 | mut ent = (val bucket.get(i)) 268 | 269 | if ent'hash == keyHash 270 | entryDeinit(ent, me) 271 | 272 | ent'key = key 273 | ent'value = value 274 | 275 | return 276 | /if 277 | 278 | i++ 279 | /while 280 | 281 | me'len++ 282 | bucket.append(entryNew(keyHash, key, value)) 283 | 284 | /method 285 | 286 | 287 | method Hash.rehash() 288 | mut old = me'buckets 289 | mut oldLen = old.len() 290 | 291 | init(me, 2 * oldLen, me'hf) 292 | 293 | mut i uintptr = 0 294 | 295 | while i < oldLen 296 | mut bucket = (val old.get(i)) 297 | 298 | if bucket? 299 | mut buckLen = bucket.len() 300 | mut j uintptr = 0 301 | 302 | while j < buckLen 303 | mut ent = (val bucket.get(j)) 304 | 305 | me.put(ent'key, ent'value) 306 | 307 | mem:free(ent) 308 | 309 | j++ 310 | /while 311 | 312 | list:free(bucket) 313 | /if 314 | 315 | i++ 316 | /while 317 | 318 | vect:free(old) 319 | /method 320 | 321 | 322 | method Hash.remove(key data) bool 323 | if me.len() == 0 324 | return false 325 | /if 326 | 327 | mut keyHash = me'hf(key) 328 | mut bucketsNum = me'buckets.cap() 329 | mut index = keyHash mod bucketsNum 330 | 331 | mut bucket = (val me'buckets.get(index)) 332 | 333 | if not bucket? 334 | return false 335 | /if 336 | 337 | mut i uintptr = 0 338 | mut buckLen = bucket.len() 339 | 340 | while i < buckLen 341 | mut elem = (val bucket.get(i)) 342 | 343 | if elem'hash == keyHash 344 | bucket.remove(i, null) 345 | 346 | if me'freeKey? 347 | me'freeKey(elem'key) 348 | /if 349 | 350 | if me'freeVal? 351 | me'freeVal(elem'value) 352 | /if 353 | 354 | mem:free(elem) 355 | 356 | me'len-- 357 | 358 | return true 359 | /if 360 | 361 | i++ 362 | /while 363 | 364 | return false 365 | /method 366 | 367 | 368 | method Hash.setFreeFuncs(freeKey,freeVal ptr func(item data)) 369 | me'freeKey = freeKey 370 | me'freeVal = freeVal 371 | /method 372 | 373 | 374 | func strinit(hash ptr Hash, cap uintptr) ptr Hash 375 | return init(hash, cap, ptr txt:strhash) 376 | /func 377 | 378 | 379 | func strnew(cap uintptr) ptr Hash 380 | return new(cap, ptr txt:strhash) 381 | /func 382 | -------------------------------------------------------------------------------- /libfork/src/hash/hashiter.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module hash 12 | 13 | 14 | import list 15 | import mem 16 | import pair 17 | import vect 18 | 19 | 20 | alias Iter struct ( 21 | hash ptr Hash, 22 | curBucket ptr list:List, 23 | buckIndex,pos uintptr, 24 | end bool 25 | ) 26 | 27 | 28 | method Hash.iter() ptr Iter 29 | mut iter = (mem:zalloc(size(Iter))) 30 | 31 | iter'hash = me 32 | 33 | if me'buckets.len() > 0 34 | iter'curBucket = (val me'buckets.get(0)) 35 | else 36 | iter'end = true 37 | /if 38 | 39 | return iter 40 | /method 41 | 42 | 43 | method Iter.loadNextBucket() 44 | me'curBucket = null 45 | 46 | while (not me'curBucket?) or me'curBucket.len() == 0 47 | me'buckIndex++ 48 | 49 | # if we've reached the last bucket, return null and stop 50 | if me'buckIndex >= me'hash'buckets.len() 51 | me'end = true 52 | break 53 | /if 54 | 55 | me'curBucket = (val me'hash'buckets.get(me'buckIndex)) 56 | me'pos = 0 57 | /while 58 | /method 59 | 60 | 61 | method Iter.next() ptr pair:Pair 62 | # load next bucket 63 | if not me'curBucket? or me'curBucket.len() == 0 or me'pos == me'curBucket.len() 64 | me.loadNextBucket() 65 | /if 66 | 67 | if me'end 68 | return null 69 | /if 70 | 71 | mut ent = (val me'curBucket.get(me'pos)) 72 | me'pos++ 73 | 74 | return pair:new(ent'key, ent'value) 75 | /method 76 | 77 | 78 | func iterFree(iter ptr Iter) 79 | mem:free(iter) 80 | /func 81 | -------------------------------------------------------------------------------- /libfork/src/hash/hashnum.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module hash 12 | 13 | 14 | import txt 15 | 16 | 17 | alias hashfn ptr func(item data) uintptr 18 | alias HashNum uintptr 19 | 20 | 21 | mut weirdNumber = size(uintptr) - 1 22 | 23 | 24 | func hnNum(hn ptr HashNum, n uintptr) HashNum 25 | return val hn = val hn * weirdNumber + n 26 | /func 27 | 28 | 29 | func hnString(hn ptr HashNum, str ptr uint8) HashNum 30 | return val hn = val hn * weirdNumber + txt:strhash(str) 31 | /func 32 | -------------------------------------------------------------------------------- /libfork/src/io/streams.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module io 12 | 13 | 14 | import err 15 | import mem 16 | import txt 17 | 18 | 19 | # cookie structure 20 | 21 | alias closefunc func(handl data, err ptr ptr err:Error) bool 22 | alias readfunc func(handl data, buf ptr uint8, bufSize intptr, err ptr ptr err:Error, eof ptr bool) uintptr 23 | alias writefunc func(handl data, buf ptr uint8, bufSize intptr, err ptr ptr err:Error) uintptr 24 | 25 | 26 | alias Cookie struct ( 27 | priv8 data, 28 | cfn ptr closefunc, 29 | rfn ptr readfunc, 30 | wfn ptr writefunc 31 | ) 32 | 33 | 34 | # stream structure 35 | 36 | alias Stream struct ( 37 | cookie Cookie, 38 | eof bool, 39 | error ptr err:Error, 40 | inout uint8 41 | ) 42 | 43 | 44 | mut STREAM_IN uint8 = 1 45 | mut STREAM_OUT uint8 = 2 46 | mut STREAM_INOUT uint8 = 3 47 | 48 | 49 | # Stream functions 50 | 51 | func streamClose(stream ptr Stream) bool 52 | mut ret = stream'cookie'cfn(stream'cookie'priv8, ptr stream'error) 53 | 54 | mem:free(stream) 55 | return ret 56 | /func 57 | 58 | 59 | func streamNew(priv8 data, 60 | rfn ptr readfunc, 61 | wfn ptr writefunc, 62 | cfn ptr closefunc) ptr Stream 63 | 64 | mut ret = (mem:zalloc(size(Stream))) 65 | ret'cookie'priv8 = priv8 66 | 67 | if wfn? 68 | ret'inout = ret'inout | STREAM_OUT 69 | /if 70 | 71 | if rfn? 72 | ret'inout = ret'inout | STREAM_IN 73 | /if 74 | 75 | ret'cookie'wfn = wfn 76 | ret'cookie'rfn = rfn 77 | ret'cookie'cfn = cfn 78 | return ret 79 | /func 80 | 81 | 82 | # Stream methods 83 | 84 | method Stream.ended() bool 85 | return me'eof 86 | /method 87 | 88 | 89 | method Stream.error() ptr err:Error 90 | return me'error 91 | /method 92 | 93 | 94 | method Stream.read(buf data, len intptr) uintptr 95 | if (me'inout & STREAM_IN) == 0 96 | me'error = err:new("stream opened write-only") 97 | return 0 98 | /if 99 | 100 | return me'cookie'rfn(me'cookie'priv8, (buf), len, ptr me'error, ptr me'eof) 101 | /method 102 | 103 | 104 | method Stream.readStr(str ptr uint8, len intptr) uintptr 105 | me.read(str, len) 106 | /method 107 | 108 | 109 | method Stream.write(buf data, len intptr) uintptr 110 | if (me'inout & STREAM_OUT) == 0 111 | me'error = err:new("stream opened read-only") 112 | return 0 113 | /if 114 | 115 | return me'cookie'wfn(me'cookie'priv8, (buf), len, ptr me'error) 116 | /method 117 | 118 | 119 | method Stream.writeStr(string ptr uint8) uintptr 120 | me.write(string, (txt:strlen(string))) 121 | /method 122 | -------------------------------------------------------------------------------- /libfork/src/io/ttystream.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module io 12 | 13 | 14 | import err 15 | import tty 16 | import txt 17 | 18 | 19 | func ttyCookieOut(handl data, 20 | buf ptr uint8, 21 | bufSize intptr, 22 | err ptr ptr err:Error) uintptr 23 | 24 | tty:out(buf) 25 | 26 | return txt:strlen(buf) 27 | /func 28 | 29 | 30 | func ttyCookieCloseFake(handl data, err ptr ptr err:Error) bool 31 | return true 32 | /func 33 | 34 | 35 | func ttyStream() Stream 36 | mut ret Stream 37 | 38 | ret'cookie'cfn = ptr ttyCookieCloseFake 39 | ret'cookie'wfn = ptr ttyCookieOut 40 | ret'eof = false 41 | ret'error = null 42 | ret'inout = STREAM_OUT 43 | 44 | return ret 45 | /func 46 | -------------------------------------------------------------------------------- /libfork/src/kv/keyvaluelist.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | # KVList'list contains (key, data) pairs; contents are there freed itereratively. 11 | # KVList'hash contains (key, (index,data)) pairs; the only freed thing there is 12 | # the (index, data) pair itself (data is left untouched because it has been 13 | # freed before) 14 | 15 | module kv 16 | 17 | 18 | import hash 19 | import list 20 | import mem 21 | import pair 22 | import sort 23 | import tty 24 | import txt 25 | 26 | 27 | alias KVList struct( 28 | hash hash:Hash, 29 | list list:List, 30 | freeKey,freeVal ptr func(item data) 31 | ) 32 | 33 | 34 | # KVList init/deinit functions 35 | 36 | func deinit(kv ptr KVList) 37 | kv.freeContents() 38 | 39 | hash:deinit(ptr kv'hash) 40 | list:deinitAll(ptr kv'list, ptr pair:free) 41 | /func 42 | 43 | 44 | func free(kv ptr KVList) 45 | if kv? 46 | deinit(kv) 47 | mem:free(kv) 48 | /if 49 | /func 50 | 51 | 52 | func init(kv ptr KVList, cap uintptr, hf hash:hashfn) ptr KVList 53 | mem:set(kv, 0, size(KVList)) 54 | 55 | hash:init(ptr kv'hash, cap, hf) 56 | 57 | kv'hash.setFreeFuncs(null, ptr hashFreePairs) 58 | 59 | list:init(ptr kv'list) 60 | 61 | return kv 62 | /func 63 | 64 | 65 | func new(cap uintptr, hf hash:hashfn) ptr KVList 66 | return init((mem:alloc(size(KVList))), cap, hf) 67 | /func 68 | 69 | 70 | func strinit(kv ptr KVList, cap uintptr) ptr KVList 71 | return init(kv, cap, ptr txt:strhash) 72 | /func 73 | 74 | 75 | func strnew(cap uintptr) ptr KVList 76 | return new(cap, ptr txt:strhash) 77 | /func 78 | 79 | 80 | # KVList methods 81 | 82 | method KVList.clone() ptr KVList 83 | mut ret = new(me'hash'buckets'cap, me'hash'hf) 84 | 85 | mut len = me.len() 86 | mut i uintptr = 0 87 | 88 | while i < len 89 | mut elem = me.getAt(i) 90 | ret.put(elem'key, elem'value) 91 | 92 | i++ 93 | /while 94 | 95 | return ret 96 | /method 97 | 98 | 99 | method KVList.contains(key data) bool 100 | return me'hash.contains(key) 101 | /method 102 | 103 | 104 | method KVList.first() ptr pair:Pair 105 | return me'list.len() > 0 => (val me'list.get(0)) || null 106 | /method 107 | 108 | 109 | method KVList.fixIndices(pos uintptr) 110 | mut len = me'list.len() 111 | 112 | while pos < len 113 | mut pair = me.getAt(pos) 114 | mut indexValue = (me'hash.get(pair'key)) 115 | 116 | indexValue'key = (pos) 117 | 118 | pos++ 119 | /while 120 | /method 121 | 122 | 123 | method KVList.freePairContents(pair ptr pair:Pair) 124 | if me'freeKey? 125 | me'freeKey(pair'key) 126 | /if 127 | 128 | if me'freeVal? 129 | me'freeVal(pair'value) 130 | /if 131 | /method 132 | 133 | 134 | method KVList.freeContents() 135 | mut len = me.len() 136 | mut i uintptr = 0 137 | 138 | while i < len 139 | me.freePairContents(me.getAt(i)) 140 | 141 | i++ 142 | /while 143 | /method 144 | 145 | 146 | method KVList.get(key data) data 147 | mut indexValue = (me'hash.get(key)) 148 | 149 | return indexValue? => indexValue'value || null 150 | /method 151 | 152 | 153 | method KVList.getAt(index uintptr) ptr pair:Pair 154 | mut ret = me'list.get(index) 155 | return ret? => (val ret) || null 156 | /method 157 | 158 | 159 | method KVList.getPos(key data) intptr 160 | mut indexValue = (me'hash.get(key)) 161 | 162 | return indexValue? => (indexValue'key) || -1 163 | /method 164 | 165 | 166 | method KVList.len() uintptr 167 | return me'list.len() 168 | /method 169 | 170 | 171 | method KVList.print() 172 | 173 | tty:out("[ ") 174 | 175 | mut len = me.len() 176 | mut i uintptr = 0 177 | 178 | while i < len 179 | if i > 0 180 | tty:out(", ") 181 | /if 182 | 183 | mut pair = me.getAt(i) 184 | 185 | tty:out((pair'key)) 186 | tty:out(": ") 187 | tty:out((pair'value)) 188 | 189 | i++ 190 | /while 191 | 192 | tty:out(" ]") 193 | 194 | /method 195 | 196 | 197 | method KVList.put(key data, value data) 198 | mut indexValue = (me'hash.get(key)) 199 | 200 | # if no key matches, then create a new element in list and hash 201 | # The index of this element will be the current length of the list (obviously). 202 | if not indexValue? 203 | indexValue = pair:new((me'list.len()), value) 204 | 205 | me'hash.put(key, indexValue) 206 | me'list.append(pair:new(key, value)) 207 | else 208 | mut index = (indexValue'key) 209 | mut pair = (val me'list.get(index)) 210 | 211 | me.freePairContents(pair) 212 | # bug: check for double frees. Won't fix because it's better to improve the 213 | # language with destructors and methods, then making hacks. 214 | pair'key = key 215 | pair'value = indexValue'value = value 216 | /if 217 | /method 218 | 219 | 220 | method KVList.remove(key data) bool 221 | 222 | # pair value will be discarded. 223 | mut pos = me.getPos(key) 224 | 225 | if pos >= 0 226 | mut pair = (val me'list.get(pos)) 227 | 228 | me.freePairContents(pair) 229 | 230 | me'list.remove(pos, ptr pair:free) 231 | 232 | me'hash.remove(key) 233 | 234 | me.fixIndices(pos) 235 | 236 | return true 237 | /if 238 | 239 | return false 240 | /method 241 | 242 | 243 | method KVList.setFreeFuncs(freeKey,freeVal ptr func(item data)) 244 | me'freeKey = freeKey 245 | me'freeVal = freeVal 246 | /method 247 | 248 | 249 | func hashFreePairs(pairV data) 250 | mut pair = (pairV) 251 | 252 | pair:free(pair) 253 | /func 254 | -------------------------------------------------------------------------------- /libfork/src/map/iter.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module map 12 | 13 | 14 | import mem 15 | import pair 16 | 17 | 18 | alias Iter struct ( 19 | map ptr Map, 20 | lastKey data, 21 | begin bool 22 | ) 23 | 24 | 25 | method Map.iter() ptr Iter 26 | mut iter = (mem:alloc(size(Iter))) 27 | iter'map = me 28 | iter'lastKey = null 29 | iter'begin = true 30 | return iter 31 | /method 32 | 33 | 34 | method Iter.intNext(node ptr Node) ptr pair:Pair 35 | 36 | if not node? 37 | return null 38 | /if 39 | 40 | mut cmp = node'cmp(me'lastKey, node'key) 41 | 42 | #lastKey < node'key 43 | if cmp < 0 44 | mut pair = me.intNext(node'left) 45 | if pair? 46 | return pair 47 | /if 48 | 49 | return nodeMkpair(node) 50 | /if 51 | 52 | return me.intNext(node'right) 53 | /method 54 | 55 | 56 | method Iter.next() ptr pair:Pair 57 | mut root = me'map'root 58 | 59 | if not root? 60 | return null 61 | /if 62 | 63 | if me'begin 64 | me'begin = false 65 | mut pair = nodeMinpair(root) 66 | me'lastKey = pair'key 67 | return pair 68 | /if 69 | 70 | mut pair = me.intNext(me'map'root) 71 | 72 | if pair? 73 | me'lastKey = pair'key 74 | /if 75 | 76 | return pair 77 | 78 | /method 79 | 80 | 81 | func iterFree(iter ptr Iter) 82 | mem:free(iter) 83 | /func 84 | -------------------------------------------------------------------------------- /libfork/src/math/math.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module math 12 | 13 | 14 | func abs(num intptr) uintptr 15 | return num < 0 => -num || num 16 | /func 17 | 18 | 19 | func __forkpow(base,exp uintptr) uintptr 20 | 21 | if exp == 0 22 | return 1 23 | /if 24 | 25 | if base == 1 26 | return 1 27 | /if 28 | 29 | if base == 0 30 | return 0 31 | /if 32 | 33 | mut ret uintptr = 1 34 | mut i uintptr = 1 35 | 36 | while i <= exp 37 | ret = ret * base 38 | i++ 39 | /while 40 | 41 | return ret 42 | 43 | /func 44 | -------------------------------------------------------------------------------- /libfork/src/mem/alloc.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module mem 12 | 13 | 14 | import proc 15 | 16 | 17 | func alloc(len uintptr) data 18 | decl func malloc(cap uintptr) data 19 | mut ret = malloc(len) 20 | 21 | if not ret? and len != 0 22 | proc:panic("bad alloc") 23 | /if 24 | 25 | return ret 26 | /func 27 | 28 | 29 | func zalloc(len uintptr) data 30 | decl func calloc(len uintptr, storageSize uintptr) data 31 | mut ret = calloc(1, len) 32 | 33 | if not ret? and len != 0 34 | proc:panic("bad alloc") 35 | /if 36 | 37 | return ret 38 | /func 39 | 40 | 41 | func free(d data) 42 | decl func free(d data) 43 | 44 | free(d) 45 | /func 46 | -------------------------------------------------------------------------------- /libfork/src/mem/buffer.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module mem 12 | 13 | 14 | # buffer structure 15 | alias Buffer struct ( 16 | base, work ptr uint8, 17 | len, cap uintptr 18 | ) 19 | 20 | 21 | # buffer init/deinit functions 22 | 23 | 24 | func deinitBuffer(buf ptr Buffer) 25 | free(buf'base) 26 | /func 27 | 28 | 29 | func freeBuffer(buf ptr Buffer) 30 | if buf? 31 | deinitBuffer(buf) 32 | free(buf) 33 | /if 34 | /func 35 | 36 | 37 | func initBuffer(buf ptr Buffer, cap uintptr) ptr Buffer 38 | buf'work = buf'base = (alloc(cap)) 39 | buf'cap = cap 40 | 41 | return buf 42 | /func 43 | 44 | 45 | func newBuffer(cap uintptr) ptr Buffer 46 | mut buf = (zalloc(size(Buffer))) 47 | 48 | return initBuffer(buf, cap) 49 | /func 50 | 51 | 52 | func unwrapBuffer(buf ptr Buffer) {bytes ptr uint8, len uintptr} 53 | mut ret = buf'base 54 | mut len = buf.len() 55 | free(buf) 56 | 57 | return {ret,len} 58 | /func 59 | 60 | 61 | # buffer methods 62 | 63 | method Buffer.add(bytes data, len uintptr) ptr Buffer 64 | mut req = me.len() + len 65 | 66 | me.ensure(req, 0) 67 | 68 | copy(me'work, bytes, len) 69 | 70 | me'len = req 71 | me'work = me'base + req 72 | 73 | return me 74 | /method 75 | 76 | 77 | method Buffer.addByte(b uint8) ptr Buffer 78 | me.ensure(me.len() + 1, 0) 79 | 80 | val me'work = b 81 | me'len++ 82 | me'work++ 83 | 84 | return me 85 | /method 86 | 87 | 88 | method Buffer.prepend(bytes data, len uintptr) ptr Buffer 89 | mut req = me.len() + len 90 | 91 | me.ensure(req, len) 92 | 93 | me'len = me'len + len 94 | me'work = me'base + me'len 95 | 96 | copy(me'base, bytes, len) 97 | 98 | return me 99 | /method 100 | 101 | 102 | method Buffer.prependByte(b uint8) ptr Buffer 103 | me.prepend(ptr b, 1) 104 | 105 | return me 106 | /method 107 | 108 | 109 | method Buffer.ensure(newcap,offset uintptr) 110 | # If we already have the needed capacity, just shift stuff of the required 111 | # offset 112 | if me'cap >= newcap 113 | if offset > 0 114 | move(me'base + offset, me'base, me.len()) 115 | /if 116 | 117 | return 118 | /if 119 | 120 | while me'cap < newcap 121 | me'cap = (3 * me'cap) / 2 # 1.5x increase steps 122 | /while 123 | 124 | mut new = (alloc(me'cap)) 125 | copy(new + offset, me'base, me'len) 126 | free(me'base) 127 | me'base = new 128 | me'work = me'base + me'len 129 | /method 130 | 131 | 132 | method Buffer.len() uintptr 133 | return me'len 134 | /method 135 | -------------------------------------------------------------------------------- /libfork/src/mem/memmove.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module mem 12 | 13 | 14 | func copy(dest data, src data, len uintptr) data 15 | decl func memcpy(dest data, src data, len uintptr) data 16 | 17 | return memcpy(dest, src, len) 18 | /func 19 | 20 | 21 | func move(dest data, src data, len uintptr) data 22 | decl func memmove(dest data, src data, len uintptr) data 23 | 24 | return memmove(dest, src, len) 25 | /func 26 | 27 | 28 | func set(dest data, value uintptr, len uintptr) data 29 | decl func memset(dest data, value uintptr, len uintptr) data 30 | 31 | return memset(dest, value, len) 32 | /func 33 | 34 | 35 | func zero(dest data, len uintptr) data 36 | return set(dest, 0, len) 37 | /func 38 | -------------------------------------------------------------------------------- /libfork/src/memutils/freepool.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module memutils 12 | 13 | 14 | import list 15 | import mem 16 | 17 | 18 | alias FreePool struct( 19 | ptrs ptr list:List, 20 | freeFunc ptr func(item data) 21 | ) 22 | 23 | 24 | func fpFree(fp ptr FreePool) 25 | if fp? 26 | list:freeAll(fp'ptrs, fp'freeFunc) 27 | mem:free(fp) 28 | /if 29 | /func 30 | 31 | func fpNew(freeFunc ptr func(item data)) ptr FreePool 32 | mut ret = (mem:alloc(size(FreePool))) 33 | ret'ptrs = list:new() 34 | ret'freeFunc = freeFunc 35 | 36 | return ret 37 | /func 38 | 39 | 40 | method FreePool.alloc(len uintptr) data 41 | mut ret = mem:alloc(len) 42 | me'ptrs.append(ret) 43 | 44 | return ret 45 | /method 46 | 47 | 48 | method FreePool.zalloc(len uintptr) data 49 | mut ret = mem:zalloc(len) 50 | me'ptrs.append(ret) 51 | 52 | return ret 53 | /method 54 | -------------------------------------------------------------------------------- /libfork/src/memutils/ref.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module memutils 12 | 13 | 14 | import err 15 | import list 16 | import txt 17 | 18 | 19 | alias Ref struct ( 20 | count uintptr, 21 | freeFunc ptr func(item data) 22 | ) 23 | 24 | 25 | func incRef(refc data) 26 | if refc? 27 | (refc)'count++ 28 | /if 29 | /func 30 | 31 | 32 | func decRef(refc data) 33 | if refc? 34 | mut ref = (refc) 35 | ref'count-- 36 | if ref'count < 1 37 | ref'freeFunc(refc) 38 | /if 39 | /if 40 | /func 41 | -------------------------------------------------------------------------------- /libfork/src/misc/numrepr.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module misc 12 | 13 | import mem 14 | import tty 15 | import txt 16 | 17 | 18 | func low(n uint32) ptr uint8 19 | if n == 0 20 | return "zero" 21 | /if 22 | 23 | if n == 1 24 | return "one" 25 | /if 26 | 27 | if n == 2 28 | return "two" 29 | /if 30 | 31 | if n == 3 32 | return "three" 33 | /if 34 | 35 | if n == 4 36 | return "four" 37 | /if 38 | 39 | if n == 5 40 | return "five" 41 | /if 42 | 43 | if n == 6 44 | return "six" 45 | /if 46 | 47 | if n == 7 48 | return "seven" 49 | /if 50 | 51 | if n == 8 52 | return "eight" 53 | /if 54 | 55 | if n == 9 56 | return "nine" 57 | /if 58 | 59 | if n == 10 60 | return "ten" 61 | /if 62 | 63 | if n == 11 64 | return "eleven" 65 | /if 66 | 67 | if n == 12 68 | return "twelve" 69 | /if 70 | 71 | if n == 13 72 | return "thirteen" 73 | /if 74 | 75 | if n == 14 76 | return "fourteen" 77 | /if 78 | 79 | if n == 15 80 | return "fifteen" 81 | /if 82 | 83 | if n == 16 84 | return "sixteen" 85 | /if 86 | 87 | if n == 17 88 | return "seventeen" 89 | /if 90 | 91 | if n == 18 92 | return "eighteen" 93 | /if 94 | 95 | if n == 19 96 | return "nineteen" 97 | /if 98 | 99 | return null 100 | /func 101 | 102 | 103 | func tens(n uint32) ptr uint8 104 | mut t = n / 10 105 | 106 | if t == 2 107 | return "twenty" 108 | /if 109 | 110 | if t == 3 111 | return "thirty" 112 | /if 113 | 114 | if t == 4 115 | return "fourty" 116 | /if 117 | 118 | if t == 5 119 | return "fifty" 120 | /if 121 | 122 | if t == 6 123 | return "sixty" 124 | /if 125 | 126 | if t == 7 127 | return "seventy" 128 | /if 129 | 130 | if t == 8 131 | return "eighty" 132 | /if 133 | 134 | if t == 9 135 | return "ninety" 136 | /if 137 | /func 138 | 139 | 140 | func twociphers(cs ptr txt:Charstash, n uint32) 141 | cs.add(tens(n)) 142 | 143 | mut units = n mod 10 144 | 145 | if units > 0 146 | cs.add(low(units)) 147 | /if 148 | /func 149 | 150 | 151 | func repr(cs ptr txt:Charstash, n uint32) 152 | if n < 20 153 | cs.add(low(n)) 154 | return 155 | /if 156 | 157 | if n < 100 158 | twociphers(cs, n) 159 | return 160 | /if 161 | 162 | if n < 1000 163 | cs.add(low(n / 100)) 164 | cs.add("hundred") 165 | repr(cs, n mod 100) 166 | return 167 | /if 168 | 169 | if n < 1000000 170 | repr(cs, n / 1000) 171 | cs.add("thousand") 172 | repr(cs, n mod 1000) 173 | return 174 | /if 175 | 176 | if n < 1000000000 177 | repr(cs, n / 1000000) 178 | cs.add("million") 179 | repr(cs, n mod 1000000) 180 | return 181 | /if 182 | 183 | # otherwise it's from 1 billion to 2**32 - 1. Lucky you. 184 | 185 | cs.add(low(n / 1000000000)) 186 | cs.add("billion") 187 | repr(cs, n mod 1000000000) 188 | /func 189 | 190 | 191 | func representNum(n int32) ptr uint8 192 | mut cs = txt:newCs(20) 193 | 194 | if n < 0 195 | cs.add("minus") 196 | 197 | n = -n 198 | /if 199 | 200 | repr(cs, (n)) 201 | 202 | return txt:unwrapCs(cs) 203 | /func 204 | -------------------------------------------------------------------------------- /libfork/src/misc/utils.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module misc 12 | 13 | 14 | import err 15 | import list 16 | import mem 17 | import txt 18 | 19 | 20 | func charIsIdVal(ch uint8) bool 21 | if (ch >= 48) and (ch <= 57) #is a number 22 | return true 23 | /if 24 | 25 | if (ch >= 65) and (ch <= 90) #is an uppercase letter 26 | return true 27 | /if 28 | 29 | if (ch >= 97) and (ch <= 122) #is a lowcase letter 30 | return true 31 | /if 32 | 33 | if ch == 95 #is a `_` 34 | return true 35 | /if 36 | 37 | return false 38 | /func 39 | 40 | 41 | func charIsBackslash(ch uint8) bool 42 | return ch == 92 43 | /func 44 | 45 | 46 | func charIsControl(ch uint8) bool 47 | return ch < 20 or ch > 126 48 | /func 49 | 50 | 51 | func charIsPar(ch uint8) bool 52 | #40 == `(`, 41 == `)`, 91 == `[`, 93 == `]` 53 | return ch == 40 or ch == 41 or ch == 91 or ch == 93 54 | /func 55 | 56 | 57 | func charIsWhite(ch uint8) bool 58 | #32 == ` `, 10 == `\n`, 13 == `\r`, 12 == `\f`, 11 == `\v`, 9 == `\t` 59 | return ch == 32 or ch == 10 or ch == 13 or ch == 12 or ch == 11 or ch == 9 60 | /func 61 | 62 | # backslash is not a symbol. It should never be grouped with anything. 63 | func charIsSym(ch uint8) bool 64 | return not charIsIdVal(ch) and not charIsPar(ch) and not charIsWhite(ch) and not charIsBackslash(ch) 65 | /func 66 | 67 | 68 | func charCanBeInString(ch uint8, escape bool) bool 69 | if not escape and ch == 34 # `"` 70 | return false #if the matching " is found, then stop 71 | /if 72 | 73 | return not charIsControl(ch) 74 | /func 75 | 76 | 77 | func strIsUInt(str ptr uint8) bool 78 | while val str != 0 79 | if (val str < 48) or (val str > 57) # current letter is not an ASCII number 80 | return false 81 | /if 82 | 83 | str++ 84 | /while 85 | 86 | return true 87 | /func 88 | 89 | 90 | func listContains(list ptr list:List, value ptr uint8) bool 91 | mut i uintptr = 0 92 | mut len = list.len() 93 | 94 | 95 | mut clone = val list 96 | 97 | # this fixes a weird bug in list:List that I haven't found yet. 98 | list.seekZero() 99 | 100 | while i < len 101 | mut ptrElem = list.get(i) 102 | mut elem = (val ptrElem) 103 | 104 | if txt:strequals(elem, value) 105 | return true 106 | /if 107 | 108 | i++ 109 | /while 110 | 111 | return false 112 | /func 113 | 114 | 115 | func listDumpHierarchyIntoCS(list ptr list:List, cs ptr txt:Charstash) 116 | mut len = list.len() 117 | 118 | cs.add("(") 119 | 120 | if len > 1 121 | 122 | mut i = (len) 123 | 124 | while i > 0 125 | i-- 126 | 127 | cs.add((val list.get(i))) 128 | 129 | cs.add(" => ") 130 | /while 131 | 132 | cs.add((val list.get(len - 1))) 133 | else 134 | cs.add("alias of itself") 135 | /if 136 | 137 | cs.add(")") 138 | /func 139 | -------------------------------------------------------------------------------- /libfork/src/pair/pair.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module pair 12 | 13 | 14 | import mem 15 | 16 | 17 | # pair structure 18 | alias Pair struct ( 19 | key, value data 20 | ) 21 | 22 | 23 | func new(first,second data) ptr Pair 24 | mut pair = (mem:zalloc(size(Pair))) 25 | pair'key = first 26 | pair'value = second 27 | 28 | return pair 29 | /func 30 | 31 | 32 | func free(pair ptr Pair) 33 | mem:free(pair) 34 | /func 35 | -------------------------------------------------------------------------------- /libfork/src/proc/proc.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module proc 12 | 13 | 14 | import c 15 | 16 | 17 | alias Args struct ( 18 | len uintptr, 19 | progname ptr uint8, 20 | args ptr ptr uint8 21 | ) 22 | 23 | 24 | mut __forkprogArgs Args 25 | 26 | func args() ptr Args 27 | return ptr __forkprogArgs 28 | /func 29 | 30 | 31 | func abort() 32 | decl func abort() 33 | 34 | abort() 35 | /func 36 | 37 | 38 | func exit(retval int16) 39 | decl func exit(retval int16) 40 | 41 | exit(retval) 42 | /func 43 | 44 | 45 | func getenv(variable ptr uint8) ptr uint8 46 | decl func getenv(variable ptr uint8) ptr uint8 47 | 48 | return getenv(variable) 49 | /func 50 | 51 | 52 | func panic(msg ptr uint8) 53 | decl func fputs(str ptr uint8, file c:CFILE) 54 | mut stderr = c:stderr_file() 55 | fputs("panic: ", stderr) 56 | fputs(msg, stderr) 57 | fputs("\n", stderr) 58 | 59 | abort() 60 | /func 61 | -------------------------------------------------------------------------------- /libfork/src/rt/rt.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | import proc 12 | 13 | 14 | decl func __fork_entry() 15 | 16 | 17 | func main(argc intptr, argv ptr ptr uint8) int8 18 | mut forkArgs = proc:args() 19 | forkArgs'len = (argc - 1) 20 | forkArgs'progname = val argv 21 | forkArgs'args = argv + 1 22 | __fork_entry() 23 | return 0 24 | /func 25 | -------------------------------------------------------------------------------- /libfork/src/set/set.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module set 12 | 13 | 14 | import hash 15 | import mem 16 | import tty 17 | import txt 18 | 19 | 20 | alias Set struct( 21 | hash ptr hash:Hash 22 | ) 23 | 24 | 25 | # set init/deinit functions 26 | 27 | func deinit(set ptr Set) 28 | hash:free(set'hash) 29 | /func 30 | 31 | 32 | func free(set ptr Set) 33 | if set? 34 | deinit(set) 35 | mem:free(set) 36 | /if 37 | /func 38 | 39 | 40 | func init(set ptr Set, cap uintptr, hf hash:hashfn) ptr Set 41 | set'hash = hash:new(cap, hf) 42 | 43 | return set 44 | /func 45 | 46 | 47 | func new(cap uintptr, hf hash:hashfn) ptr Set 48 | return init((mem:alloc(size(Set))), cap, hf) 49 | /func 50 | 51 | 52 | # set methods 53 | 54 | method Set.clone() ptr Set 55 | mut newSet = (mem:alloc(size(Set))) 56 | 57 | newSet'hash = me'hash.clone() 58 | 59 | return newSet 60 | /method 61 | 62 | 63 | method Set.contains(value data) bool 64 | return me'hash.contains(value) 65 | /method 66 | 67 | 68 | method Set.len() uintptr 69 | return me'hash.len() 70 | /method 71 | 72 | 73 | method Set.print() 74 | # TODO: complete 75 | 76 | tty:out("[ ") 77 | 78 | mut siter = me.iter() 79 | 80 | mut item data = null 81 | mut first = true 82 | 83 | while (item = siter.next())? 84 | if first 85 | first = false 86 | else 87 | tty:out(", ") 88 | /if 89 | 90 | tty:out((item)) 91 | /while 92 | 93 | iterFree(siter) 94 | 95 | tty:out(" ]") 96 | /method 97 | 98 | 99 | method Set.put(value data) 100 | me'hash.put(value, null) 101 | /method 102 | 103 | 104 | method Set.remove(key data) bool 105 | return me'hash.remove(key) 106 | /method 107 | 108 | 109 | method Set.setFreeFunc(ff ptr func(item data)) 110 | me'hash.setFreeFuncs(ff, null) 111 | /method 112 | 113 | 114 | func strinit(set ptr Set, cap uintptr) ptr Set 115 | return init(set, cap, ptr txt:strhash) 116 | /func 117 | 118 | 119 | func strnew(cap uintptr) ptr Set 120 | return new(cap, ptr txt:strhash) 121 | /func 122 | -------------------------------------------------------------------------------- /libfork/src/set/setiter.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module set 12 | 13 | 14 | import hash 15 | import mem 16 | import pair 17 | 18 | 19 | alias Iter struct ( 20 | iter ptr hash:Iter 21 | ) 22 | 23 | 24 | method Set.iter() ptr Iter 25 | mut iter = (mem:zalloc(size(Iter))) 26 | 27 | iter'iter = me'hash.iter() 28 | 29 | return iter 30 | /method 31 | 32 | 33 | method Iter.next() data 34 | mut pair = me'iter.next() 35 | 36 | if not pair? 37 | return null 38 | /if 39 | 40 | mut ret = pair'key 41 | 42 | pair:free(pair) 43 | 44 | return ret 45 | /method 46 | 47 | 48 | func iterFree(iter ptr Iter) 49 | hash:iterFree(iter'iter) 50 | mem:free(iter) 51 | /func 52 | -------------------------------------------------------------------------------- /libfork/src/sort/sort.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module sort 12 | 13 | 14 | alias comparator ptr func(val1, val2 data) int8 15 | -------------------------------------------------------------------------------- /libfork/src/tty/console.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module tty 12 | 13 | 14 | import proc 15 | import c 16 | 17 | 18 | func err(str ptr uint8) 19 | decl func fputs(str ptr uint8, file c:CFILE) 20 | fputs(str, c:stderr_file()) 21 | /func 22 | 23 | 24 | func errch(ch uint8) 25 | decl func putc(ch uint8, file c:CFILE) 26 | putc(ch, c:stderr_file()) 27 | /func 28 | 29 | 30 | func errln(str ptr uint8) 31 | err(str) 32 | errch(10) 33 | /func 34 | 35 | 36 | func fail(str ptr uint8) 37 | err(str) 38 | proc:exit(1) 39 | /func 40 | 41 | 42 | func failln(str ptr uint8) 43 | errln(str) 44 | proc:exit(1) 45 | /func 46 | 47 | 48 | func out(str ptr uint8) 49 | decl func fputs(str ptr uint8, file c:CFILE) 50 | fputs(str, c:stdout_file()) 51 | /func 52 | 53 | 54 | func outch(ch uint8) 55 | decl func putchar(ch uint8) 56 | putchar(ch) 57 | /func 58 | 59 | 60 | func outln(str ptr uint8) 61 | decl func puts(str ptr uint8) 62 | puts(str) 63 | /func 64 | 65 | 66 | func outint(n uint64) 67 | decl func outint(n uint64) 68 | 69 | outint(n) 70 | /func 71 | -------------------------------------------------------------------------------- /libfork/src/tty/outint.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libfork, a base library for the Fork language 3 | * Copyright (C) Marco Cilloni 2014, 2015, 2016 4 | * 5 | * This Source Code Form is subject to the terms of the Mozilla Public 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 | * Exhibit B is not attached; this software is compatible with the 9 | * licenses expressed under Section 1.12 of the MPL v2. 10 | * 11 | */ 12 | 13 | #include 14 | #include 15 | 16 | 17 | void outint(uint64_t n) { 18 | printf("%" PRIu64, n); 19 | } 20 | -------------------------------------------------------------------------------- /libfork/src/txt/charstash.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module txt 12 | 13 | 14 | import mem 15 | 16 | 17 | # charstash structure 18 | alias Charstash struct ( 19 | buf mem:Buffer 20 | ) 21 | 22 | 23 | # charstash init/deinit functions 24 | 25 | func freeCs(cs ptr Charstash) 26 | if cs? 27 | mem:deinitBuffer(ptr cs'buf) 28 | mem:free(cs) 29 | /if 30 | /func 31 | 32 | 33 | func newCs(cap uintptr) ptr Charstash 34 | mut cs = (mem:zalloc(size(Charstash))) 35 | 36 | mem:initBuffer(ptr cs'buf, cap) 37 | 38 | return cs 39 | /func 40 | 41 | 42 | func unwrapCs(cs ptr Charstash) ptr uint8 43 | cs.addChar(0) 44 | 45 | mut ret = cs'buf'base 46 | mem:free(cs) 47 | 48 | return ret 49 | /func 50 | 51 | 52 | # charstash methods 53 | 54 | method Charstash.add(str ptr uint8) ptr Charstash 55 | me'buf.add(str, strlen(str)) 56 | 57 | return me 58 | /method 59 | 60 | 61 | method Charstash.addChar(ch uint8) ptr Charstash 62 | me'buf.addByte(ch) 63 | 64 | return me 65 | /method 66 | 67 | 68 | method Charstash.addInt(num uintptr) ptr Charstash 69 | mut buf [20] int8 70 | 71 | numtostr(num, ptr buf[0], 20) 72 | 73 | me.add(ptr buf[0]) 74 | 75 | return me 76 | /method 77 | 78 | 79 | method Charstash.addLine(str ptr uint8) ptr Charstash 80 | me.add(str) 81 | me.add("\n") 82 | 83 | return me 84 | /method 85 | 86 | 87 | method Charstash.addWord(str ptr uint8) ptr Charstash 88 | me.add(str) 89 | me.addChar(32) 90 | 91 | return me 92 | /method 93 | 94 | 95 | method Charstash.len() uintptr 96 | return me'buf.len() 97 | /method 98 | 99 | 100 | method Charstash.prepend(str ptr uint8) ptr Charstash 101 | me'buf.prepend(str, strlen(str)) 102 | 103 | return me 104 | /method 105 | 106 | 107 | method Charstash.prependChar(ch uint8) ptr Charstash 108 | me'buf.prependByte(ch) 109 | 110 | return me 111 | /method 112 | 113 | 114 | method Charstash.prependInt(num uintptr) ptr Charstash 115 | mut buf [20] int8 116 | 117 | numtostr(num, ptr buf[0], 20) 118 | 119 | me.prepend(ptr buf[0]) 120 | 121 | return me 122 | /method 123 | 124 | 125 | method Charstash.prependLine(str ptr uint8) ptr Charstash 126 | me.prepend(str) 127 | me.prepend("\n") 128 | 129 | return me 130 | /method 131 | 132 | 133 | method Charstash.prependWord(str ptr uint8) ptr Charstash 134 | me.prepend(str) 135 | me.prependChar(32) 136 | 137 | return me 138 | /method 139 | -------------------------------------------------------------------------------- /libfork/src/txt/strings.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module txt 12 | 13 | 14 | import mem 15 | 16 | 17 | alias Line struct( 18 | line, pos uintptr 19 | ) 20 | 21 | 22 | decl func strcmp(str1,str2 data) int32 23 | 24 | 25 | func strclone(orig ptr uint8) ptr uint8 26 | if not orig? 27 | return null 28 | /if 29 | 30 | mut len = strlen(orig) 31 | mut new = (mem:zalloc(len + 1)) 32 | strncpy(new, orig, len) 33 | return new 34 | /func 35 | 36 | 37 | func strequals(s1, s2 ptr uint8) bool 38 | if strcmp(s1,s2) == 0 39 | return true 40 | /if 41 | 42 | return false 43 | /func 44 | 45 | 46 | func strhash(str ptr uint8) uintptr 47 | mut hash uintptr = 0 48 | mut mulc = size(uintptr) - 1 49 | 50 | while val str != 0 51 | hash = mulc * hash + val str 52 | 53 | str++ 54 | /while 55 | 56 | return hash 57 | /func 58 | 59 | 60 | func strreverse(str ptr uint8, len uintptr) 61 | mut end = str + len - 1 62 | 63 | # workaround, fix sema 64 | while (str) < (end) 65 | val str = val str ^ val end 66 | val end = val end ^ val str 67 | val str = val str ^ val end 68 | 69 | str++ 70 | end-- 71 | /while 72 | /func 73 | 74 | 75 | func numtostr(num uintptr, buf ptr uint8, len uintptr) ptr uint8 76 | if len < 2 77 | return null 78 | /if 79 | 80 | if num == 0 81 | buf[0] = 48 82 | buf[1] = 0 83 | return buf 84 | /if 85 | 86 | mut i uintptr = 0 87 | mut digit uintptr 88 | while i < (len - 1) and num != 0 89 | digit = num mod 10 90 | num = num / 10 91 | buf[i] = (digit + 48) #position of 0 in ascii 92 | i++ 93 | /while 94 | 95 | strreverse(buf, i) 96 | buf[i] = 0 97 | 98 | return buf 99 | /func 100 | 101 | 102 | func strglue(strs ptr ptr uint8) ptr uint8 103 | mut cs = newCs(10) 104 | while (val strs)? 105 | cs.add(val strs) 106 | strs++ 107 | /while 108 | 109 | return unwrapCs(cs) 110 | /func 111 | 112 | 113 | func strappend(str1 ptr uint8, str2 ptr uint8) ptr uint8 114 | mut len1 = strlen(str1) 115 | mut len2 = strlen(str2) 116 | mut ret = (mem:zalloc(len1 + len2 + 1)) 117 | 118 | mem:move(ret, str1, len1) 119 | mem:move(ret + len1, str2, len2) 120 | ret[len1 + len2] = 0 121 | 122 | return ret 123 | /func 124 | 125 | 126 | func strtonum(str ptr uint8) intptr 127 | mut ret uintptr = 0 128 | mut sign int8 = 1 129 | mut len = strlen(str) 130 | 131 | if len == 0 132 | return 0 133 | /if 134 | 135 | len-- 136 | 137 | if val str == 45 and len > 1 138 | sign = -1 139 | str++ 140 | /if 141 | 142 | while val str != 0 143 | ret = ret + (val str - 48) * 10 ** len 144 | str++ 145 | len-- 146 | /while 147 | 148 | return (ret * sign) 149 | /func 150 | 151 | 152 | func strcompare(s1 data, s2 data) int8 153 | mut comp = strcmp(s1, s2) 154 | 155 | if comp > 0 156 | return 1 157 | else 158 | if comp < 0 159 | return -1 160 | else 161 | return 0 162 | /if 163 | /if 164 | /func 165 | 166 | 167 | func strBeginsWith(str, begin ptr uint8) bool 168 | decl func strncmp(s1,s2 ptr uint8, n uintptr) uint32 169 | 170 | return strncmp(str, begin, strlen(begin)) == 0 171 | /func 172 | 173 | 174 | func strEndsWith(str, end ptr uint8) bool 175 | mut strLen = strlen(str) 176 | mut endLen = strlen(end) 177 | 178 | if endLen > strLen 179 | return false 180 | /if 181 | 182 | return strequals(str + (strLen - endLen), end) 183 | /func 184 | 185 | 186 | func strlen(str ptr uint8) uintptr 187 | decl func strlen(str ptr uint8) uintptr 188 | 189 | return strlen(str) 190 | /func 191 | 192 | 193 | func strncpy(dest ptr uint8, source ptr uint8, cap uintptr) ptr uint8 194 | decl func strncpy(dest ptr uint8, source ptr uint8, cap uintptr) ptr uint8 195 | 196 | return strncpy(dest, source, cap) 197 | /func 198 | -------------------------------------------------------------------------------- /libfork/src/txt/tokenizer.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module txt 12 | 13 | 14 | import mem 15 | 16 | 17 | alias Tokenizer struct ( 18 | str ptr uint8, 19 | strlen uintptr, 20 | begin intptr, 21 | splitChar uint8 22 | ) 23 | 24 | 25 | 26 | func tokenizerFree(tkz ptr Tokenizer) 27 | if tkz? 28 | mem:free(tkz'str) 29 | mem:free(tkz) 30 | /if 31 | /func 32 | 33 | 34 | func tokenizerNew(str ptr uint8, ch uint8) ptr Tokenizer 35 | mut tkz = (mem:zalloc(size(Tokenizer))) 36 | tkz'str = strclone(str) 37 | tkz'strlen = strlen(str) 38 | tkz'splitChar = ch 39 | 40 | return tkz 41 | /func 42 | 43 | 44 | method Tokenizer.next() ptr uint8 45 | if me'begin == me'strlen 46 | return null 47 | /if 48 | 49 | mut initialBegin = me'begin 50 | 51 | while me'str[me'begin] != me'splitChar and me'begin < me'strlen 52 | me'begin++ 53 | /while 54 | 55 | mut nextLen = me'begin - initialBegin 56 | mut ret = (mem:zalloc(nextLen + 1)) # + 1 is for the null end. 57 | 58 | strncpy(ret, me'str + initialBegin, nextLen) 59 | 60 | if me'str[me'begin] == me'splitChar 61 | me'begin++ 62 | /if 63 | 64 | return ret 65 | /method 66 | -------------------------------------------------------------------------------- /libfork/src/vect/vector.fork: -------------------------------------------------------------------------------- 1 | # libfork, a base library for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module vect 12 | 13 | 14 | import mem 15 | import tty 16 | 17 | 18 | # vector structure 19 | alias Vect struct ( 20 | arr ptr uintptr, 21 | cap,len uintptr, 22 | isSlice bool 23 | ) 24 | 25 | 26 | # vector init/deinit functions 27 | 28 | 29 | func deinit(vect ptr Vect) 30 | if not vect'isSlice 31 | mem:free(vect'arr) 32 | /if 33 | /func 34 | 35 | 36 | func free(vect ptr Vect) 37 | 38 | if vect? 39 | deinit(vect) 40 | 41 | mem:free(vect) 42 | /if 43 | 44 | /func 45 | 46 | 47 | func freeAll(vect ptr Vect, freefunc ptr func(item data)) 48 | if vect? 49 | vect.freeContents(freefunc) 50 | free(vect) 51 | /if 52 | /func 53 | 54 | 55 | func init(arr ptr Vect, cap uintptr) ptr Vect 56 | mem:set(arr, 0, size(Vect)) 57 | 58 | if cap != 0 59 | arr'arr = (mem:zalloc(cap * size(uintptr))) 60 | /if 61 | 62 | arr'cap = cap 63 | return arr 64 | /func 65 | 66 | 67 | func new(cap uintptr) ptr Vect 68 | return init((mem:alloc(size(Vect))), cap) 69 | /func 70 | 71 | 72 | # vector methods 73 | 74 | method Vect.appendInt(value uintptr) bool 75 | return me.putInt(me.len(), value) 76 | /method 77 | 78 | 79 | method Vect.append(item data) bool 80 | return me.appendInt((item)) 81 | /method 82 | 83 | 84 | method Vect.cap() uintptr 85 | return me'cap 86 | /method 87 | 88 | 89 | method Vect.ensureCap(newMinCap uintptr) 90 | if newMinCap > me'cap 91 | # prevent overflows 92 | mut oldCap = me'cap 93 | 94 | # exponential growth 95 | mut newCap = oldCap + (oldCap / 2) 96 | if newCap < newMinCap 97 | newCap = newMinCap 98 | /if 99 | 100 | me.newCap(newCap) 101 | /if 102 | /method 103 | 104 | 105 | method Vect.freeContents(freefunc ptr func(item data)) 106 | if me'isSlice 107 | return 108 | /if 109 | 110 | if not freefunc? 111 | freefunc = ptr mem:free 112 | /if 113 | 114 | mut i uintptr = 0 115 | while i < me.len() 116 | freefunc((me'arr[i])) 117 | i++ 118 | /while 119 | 120 | me.prune() 121 | /method 122 | 123 | 124 | method Vect.getInt(index uintptr) ptr uintptr 125 | if me.len() <= index 126 | return null 127 | /if 128 | 129 | return me'arr + index 130 | /method 131 | 132 | 133 | method Vect.get(index uintptr) ptr data 134 | return (me.getInt(index)) 135 | /method 136 | 137 | 138 | method Vect.len() uintptr 139 | return me'len 140 | /method 141 | 142 | 143 | method Vect.newCap(newcap uintptr) 144 | mut lowercap uintptr 145 | 146 | if me.cap() > newcap 147 | lowercap = newcap 148 | else 149 | lowercap = me.cap() 150 | /if 151 | 152 | mut newarr = (mem:zalloc(newcap * size(uintptr))) 153 | 154 | mem:move(newarr, me'arr, lowercap * size(uintptr)) 155 | 156 | mem:free(me'arr) 157 | 158 | me'arr = newarr 159 | if me.len() > newcap 160 | me'len = newcap 161 | /if 162 | 163 | me'cap = newcap 164 | me'isSlice = false 165 | /method 166 | 167 | 168 | method Vect.print() 169 | mut inside = false 170 | 171 | tty:out("[ ") 172 | mut len = me.len() 173 | mut i uint8 = 0 174 | 175 | while i < len 176 | if inside 177 | tty:out(", ") 178 | else 179 | inside = true 180 | /if 181 | 182 | tty:outint(val me.getInt(i)) 183 | i++ 184 | /while 185 | 186 | tty:outln(" ]") 187 | /method 188 | 189 | 190 | method Vect.prune() 191 | mem:set(me'arr, 0, me.cap()) 192 | me'len = 0 193 | /method 194 | 195 | 196 | method Vect.putInt(index uintptr, value uintptr) bool 197 | mut newalloc = false 198 | if me.cap() <= index 199 | newalloc = true 200 | 201 | me.ensureCap(index + 1) 202 | /if 203 | 204 | me'arr[index] = value 205 | 206 | index++ 207 | 208 | if me.len() <= index 209 | me'len = index 210 | /if 211 | 212 | return newalloc 213 | /method 214 | 215 | 216 | method Vect.put(index uintptr, value data) bool 217 | return me.putInt(index, (value)) 218 | /method 219 | 220 | 221 | method Vect.slice(start uintptr, len intptr) ptr Vect 222 | mut ret = new(0) 223 | 224 | ret'isSlice = true 225 | 226 | mut meLen = me.len() 227 | 228 | if len < 0 229 | len = (meLen - start) 230 | /if 231 | 232 | if len > (meLen - start) 233 | len = (meLen - start) 234 | /if 235 | 236 | ret'cap = len 237 | ret'len = len 238 | 239 | ret'arr = me'arr + start 240 | 241 | return ret 242 | /method 243 | -------------------------------------------------------------------------------- /libforkparse/.gitignore: -------------------------------------------------------------------------------- 1 | build/* 2 | perf 3 | examples/old-examples/*.txt 4 | examples/old-examples/*.elf 5 | examples/old-examples/*.old 6 | examples/*.c 7 | examples/parsedir 8 | tests/*.err 9 | core.* 10 | -------------------------------------------------------------------------------- /libforkparse/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean tests st 2 | 3 | all: clean 4 | $(MAKE) -C src 5 | 6 | transl: 7 | $(MAKE) -C src transl 8 | 9 | clean: 10 | rm -rf build 11 | -------------------------------------------------------------------------------- /libforkparse/README.md: -------------------------------------------------------------------------------- 1 | libforkparse 2 | ============ 3 | 4 | The implementation of the reference parser and AST for the Fork language. 5 | 6 | This is incredibly alpha, so it may crash in unpredictable ways. 7 | 8 | Everything is available under the MPL v2 license. 9 | 10 | # Building 11 | libforkparse is part of [fork](http://github.com/forklang/fork), a Fork compiler. 12 | 13 | libforkparse needs transmod to compile, and they are generally developed in sync. 14 | Use a current build of Fork to build libforkparse, or otherwise get it from an official build (see fork releases for more informations). 15 | -------------------------------------------------------------------------------- /libforkparse/copyright-fork.txt: -------------------------------------------------------------------------------- 1 | # libforkparse, a full parser for the Fork language 2 | # Copyright (C) Marco Cilloni 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | -------------------------------------------------------------------------------- /libforkparse/fork.ebnf: -------------------------------------------------------------------------------- 1 | program ::= [module], {import}, { definition } 2 | module ::= 'module', id 3 | import ::= 'import', id 4 | definition ::= entry | function | mut | alias | decl | method 5 | entry ::= 'entry', stmtEnd, body, '/entry' 6 | funcHead ::= 'func', id, '(', argList, ')', [type] 7 | function ::= funcHead, stmtEnd, body, '/func' 8 | methodHead ::= 'method', idname, '.', 'id', '(', argList, ')', [type] 9 | method ::= methodHead, stmtEnd, body, '/method' 10 | argList ::= {argTypeList, ','}, argTypeList 11 | argTypeList ::= {id, ','}, id, type 12 | body ::= {stmt} 13 | stmt ::= (if | while | mut | decl | expr | return | 'break' | 'continue'), stmtEnd 14 | return ::= 'return', expr 15 | if ::= 'if', expr, stmtEnd, body, [elseBlock], '/if' 16 | while ::= 'while', expr, stmtEnd, breakBody, '/while' 17 | elseBlock ::= 'else', body 18 | mut ::= 'mut', (singleVar | structExpansion) 19 | decl ::= 'decl', (funcHead | mut | methodHead) 20 | stmtEnd ::= newLine | ';' 21 | singleVar ::= assign | declType 22 | structExpansion ::= '{', {seItem, ','}, seItem, '}', '=', expr 23 | seItem ::= id, [type] 24 | declType ::= id, type 25 | alias ::= 'alias', id, type 26 | typeModifier ::= 'val' | 'ptr' | ('[', number, ']') 27 | funcType ::= 'func', '(', [type,{',', type}], ')', [type] 28 | structType ::= newStruct | oldStruct 29 | oldStruct ::= 'struct', '(', argList, ')' 30 | newStruct ::= '{', argList, '}' 31 | type ::= [typeModifier], (id | funcType | structType) 32 | idname ::= id | ( idname, ':', id) 33 | id ::= letter, {(letter | cipher)} 34 | expr ::= assignExpr 35 | assignExpr ::= assign | conditional 36 | assign ::= unary, assignOp, assignExpr 37 | assignOp ::= '=' | '+=' | '-=' | '*=' | '/=' | '&=' | '|=' | '^=' | '**=' 38 | idname ::= id, [':', id] 39 | conditional ::= (coalesc, '=>', expr, '||', conditional) | coalesc 40 | coalesc ::= (coalesc, '??', or) | or 41 | or ::= ( or, 'or', and ) | and 42 | and ::= ( and, 'and', binOr ) | binOr 43 | binOr ::= ( binOr, '|', binAnd ) | binAnd 44 | binAnd ::= ( binAnd, '&', equality ) | equality 45 | equality ::= ( equality, ( '==' | '!=' ), comparison) | comparison 46 | comparison ::= ( comparison, compOp, shift ) | shift 47 | compOp ::= '>' | '<' | '>=' | '<=' 48 | shift ::= ( shift, ('sh<' | 'sh>'), addition) | addition 49 | addition ::= ( addition, ('+' | '-'), multiplication ) | multiplication 50 | multiplication ::= ( multiplication, ( '*', '/', 'mod' ), cast ) | cast 51 | unary ::= postfix | (unaryOp, unary) 52 | unaryOp ::= '-' | 'not' | 'ptr' | 'val' 53 | postfix ::= primary | postfixTerm 54 | postfixTerm ::= access | call | field | inc | dot | quest 55 | primary ::= idname | constant | ( '(', expr, ')' ) | cast | size | structLiteral 56 | structLiteral ::= '{', [exprList], '}' 57 | size ::= 'size', '(', type, ')' 58 | cast ::= ['cast'], '<', type, '>', '(', expr, ')' 59 | access ::= postfix, '[', expr, ']' 60 | call ::= postfix, '(', [ exprList ], ')' 61 | # mixList ::= mixArg | ( mixList, ',', mixArg) 62 | # mixArg ::= namedArg | assignExpr 63 | # namedArg ::= ''', id, '=', assignExpr, [type] 64 | exprList := assignExpr | ( exprList, ',', assignExpr ) 65 | field ::= postfix, ''', id 66 | dot ::= postfix, '.', id 67 | inc ::= postfix, ('++' | '--') 68 | quest ::= postfix, '?' 69 | constant ::= number | boolVal | 'null' | string | 'me' 70 | boolVal ::= 'true' | 'false' 71 | string ::= '"', {letter}, '"' 72 | number ::= decNumber | binNumber | hexNumber 73 | decNumber ::= ? decimal number ? 74 | hexNumber ::= ? hexadecimal number like 0xAF, letters A-F and x can be both cases ? 75 | binNumber ::= ? binary number like 0b10101, b can be both cases ? 76 | letter ::= ? any Unicode letter ? 77 | cipher ::= ? any cipher ? 78 | newLine ::= ? new line delimiter ? 79 | -------------------------------------------------------------------------------- /libforkparse/selftest.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # This script is meant to be a self test for the parser. 4 | # Assuming it fully built with the old compiler (and so it's valid), it also 5 | # must be capable to parse itself. 6 | # All the .fork and .ford files under src/ must parse. 7 | 8 | if test ! -d $PWD/build 9 | then 10 | make clean 11 | make 12 | fi 13 | 14 | 15 | I=0 16 | SUCCESS=0 17 | TOTAL=$(find src -type d ! -path src | wc -l) 18 | GREEN="\033[01;32m" 19 | RED="\033[01;31m" 20 | NORMAL="\033[00m" 21 | BEGIN=$(date +%s) 22 | 23 | for MODULE in $(find src -type d ! -path src) 24 | do 25 | let I=I+1 26 | 27 | printf "%-40s: " "$MODULE" 28 | 29 | if env FORDPATHS=$PWD/build/ford ./examples/parsedir $MODULE > /dev/null 30 | then 31 | let SUCCESS=SUCCESS+1 32 | echo -e "$GREEN success $NORMAL" 33 | else 34 | echo -e "$RED failure $NORMAL" 35 | fi 36 | 37 | done 38 | 39 | printf "Success: [%d/%d] modules in %d seconds\n" $SUCCESS $TOTAL "$(expr $(date +%s) - $BEGIN)" 40 | -------------------------------------------------------------------------------- /libforkparse/src/Makefile: -------------------------------------------------------------------------------- 1 | BUILD = $(shell pwd)/../build/ 2 | CFILES = $(BUILD)/cfiles/libforkparse/ 3 | FORDS = $(BUILD)/ford/ 4 | 5 | CFLAGS = -Wno-incompatible-pointer-types -Wno-implicit-function-declaration -Wno-incompatible-function-pointer-types -w -g -std=c99 -D_POSIX_C_SOURCE=200112L 6 | 7 | ifndef TRNS 8 | TRNS = transmod 9 | endif 10 | 11 | ifdef FORDPATHS 12 | TRNSCMD = env FORDPATHS=$(FORDPATHS):$(FORDS) $(TRNS) -fo $(FORDS) -co $(CFILES) 13 | else 14 | TRNSCMD = env FORDPATHS=$(FORDS) $(TRNS) -fo $(FORDS) -co $(CFILES) 15 | endif 16 | 17 | ifndef AR 18 | AR=ar 19 | endif 20 | 21 | ifndef RANLIB 22 | RANLIB=ranlib 23 | endif 24 | 25 | MACHINE = $(shell uname -m) 26 | 27 | ifeq ($(MACHINE), amd64) 28 | AMD64 = yes 29 | endif 30 | 31 | ifdef AMD64 32 | ifeq (,$(findstring CYGWIN,$(UNAME))) 33 | FPIC = -fPIC 34 | endif 35 | endif 36 | 37 | SONAME = 'libforkparse.so' 38 | ARNAME = 'libforkparse.a' 39 | 40 | .PHONY: all clean 41 | 42 | all: 43 | $(MAKE) transl 44 | $(MAKE) cc-ar 45 | 46 | transl: 47 | mkdir -p $(BUILD) 48 | mkdir -p $(FORDS) 49 | mkdir -p $(CFILES) 50 | $(TRNSCMD) ast 51 | $(TRNSCMD) parser 52 | 53 | cc-ar: 54 | cd $(CFILES) && $(CC) -c $(CFLAGS) $(CFILES)/*.c 55 | @printf "AR\t\t%s\n" $(ARNAME) 56 | @ $(AR) rc $(BUILD)/$(ARNAME) $(CFILES)/*.o 57 | @ $(RANLIB) $(BUILD)/$(ARNAME) 58 | 59 | clean: 60 | rm -rf $(BUILD) 61 | -------------------------------------------------------------------------------- /libforkparse/src/ast/ast.fork: -------------------------------------------------------------------------------- 1 | # libforkparse, a full parser for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module ast 12 | 13 | 14 | import hash 15 | import list 16 | import mem 17 | import memutils 18 | import txt 19 | import vect 20 | 21 | 22 | alias PNode struct( 23 | type uint16, 24 | value uintptr, 25 | parent ptr PNode, 26 | leaves ptr list:List, 27 | begin, end txt:Line, 28 | validated bool 29 | ) 30 | 31 | 32 | alias PBlock struct( 33 | node PNode, 34 | syms ptr Symtable 35 | ) 36 | 37 | 38 | alias StringDef struct( 39 | name ptr uint8, 40 | begin,end txt:Line 41 | ) 42 | 43 | 44 | alias PDecl struct( 45 | node PNode, 46 | sym ptr PSymbol, 47 | isDecl bool, 48 | methodTypeModule,methodType ptr uint8 49 | ) 50 | 51 | 52 | alias PMulDecl struct( 53 | node PNode, 54 | syms ptr list:List 55 | ) 56 | 57 | 58 | alias PRoot struct( 59 | node PBlock, 60 | moduleName ptr StringDef, 61 | fileName ptr uint8, 62 | imports ptr list:List, 63 | aliases ptr Symtable, 64 | typePool ptr memutils:FreePool, 65 | entryNode ptr PDecl, 66 | pmodule ptr PModule 67 | ) 68 | 69 | 70 | alias PExpr struct( 71 | node PNode, 72 | opType uint16, 73 | constant bool, 74 | type,sizeType ptr Type 75 | ) 76 | 77 | 78 | alias PModule struct( 79 | name ptr uint8, 80 | roots ptr vect:Vect, 81 | entryNode ptr PNode 82 | ) 83 | 84 | 85 | func methodKey(typeModule,typeName,methodName ptr uint8) ptr uint8 86 | mut cs = txt:newCs(10) 87 | 88 | if typeModule? 89 | cs.add(typeModule) 90 | cs.add(":") 91 | /if 92 | 93 | cs.add(typeName) 94 | 95 | cs.add(".") 96 | 97 | cs.add(methodName) 98 | 99 | return txt:unwrapCs(cs) 100 | /func 101 | 102 | 103 | func declKey(pdecl ptr PDecl) ptr uint8 104 | mut isMet = pdecl'node'type == PMETHOD 105 | 106 | if not isMet 107 | return txt:strclone(pdecl'sym'name) 108 | /if 109 | 110 | return methodKey(pdecl'methodTypeModule, pdecl'methodType, pdecl'sym'name) 111 | /func 112 | 113 | 114 | method PNode.findPBlock() ptr PNode 115 | if me.isBlock() 116 | return me 117 | /if 118 | 119 | if me'parent? 120 | return me'parent.findPBlock() 121 | /if 122 | 123 | return null 124 | /method 125 | 126 | 127 | method PNode.findPRoot() ptr PRoot 128 | if me.isRoot() 129 | return (me) 130 | /if 131 | 132 | if me'parent? 133 | return me'parent.findPRoot() 134 | /if 135 | 136 | return null 137 | /method 138 | 139 | 140 | method PNode.findStab() ptr Symtable 141 | mut pblock = me.findPBlock() 142 | 143 | return pblock? => (pblock)'syms || null 144 | /method 145 | 146 | 147 | method PNode.findSymInFile(name ptr uint8) {type ptr Type, 148 | root ptr PRoot} 149 | mut pblock = me.findPBlock() 150 | 151 | if pblock? 152 | mut stab = pblock.findStab() 153 | 154 | if not stab? 155 | return {null, pblock.findPRoot()} 156 | /if 157 | 158 | mut type = stab.typeof(name) 159 | 160 | if type? 161 | return {type, null} 162 | /if 163 | 164 | if pblock'parent? 165 | return {pblock'parent.findSym(name), null} 166 | /if 167 | 168 | return {null, (pblock)} 169 | /if 170 | 171 | return {null, null} 172 | /method 173 | 174 | 175 | method PNode.findSym(name ptr uint8) ptr Type 176 | mut {locSym, curRoot} = me.findSymInFile(name) 177 | 178 | if locSym? 179 | return locSym 180 | /if 181 | 182 | # try to search into the rest of the module for a global declaration. 183 | if curRoot? and curRoot'node'node.isRoot() 184 | if curRoot'pmodule? 185 | return curRoot'pmodule.findSym(name) 186 | /if 187 | /if 188 | 189 | return null 190 | /method 191 | 192 | 193 | method PNode.findSymLocal(name ptr uint8) ptr Type 194 | mut stab = me.findStab() 195 | 196 | return stab.typeof(name) 197 | /method 198 | 199 | 200 | method PNode.isBlock() bool 201 | return me'type == PBLOCK or me.isRoot() 202 | /method 203 | 204 | 205 | method PNode.isBreakContinue() bool 206 | return me'type == PBREAK or me'type == PCONTINUE 207 | /method 208 | 209 | 210 | method PNode.isDecl() bool 211 | return me'type == PALIAS or me'type == PMUT or me'type == PENTRY or me'type == PFUNCTION or me'type == PMETHOD 212 | /method 213 | 214 | 215 | method PNode.isExpr() bool 216 | return me'type == PEXPR 217 | /method 218 | 219 | 220 | method PNode.isIf() bool 221 | return me'type == PIF or me'type == PIFELSE 222 | /method 223 | 224 | 225 | method PNode.isMulDecl() bool 226 | return me'type == PMUTEXP 227 | /method 228 | 229 | 230 | method PNode.isMutOrDecl() bool 231 | return me'type == PMUT or (me.isDecl() and (me)'isDecl) 232 | /method 233 | 234 | 235 | method PNode.isReturn() bool 236 | return me'type == PRETURN 237 | /method 238 | 239 | 240 | method PNode.isRoot() bool 241 | return me'type == PROOT 242 | /method 243 | 244 | 245 | method PNode.isWhile() bool 246 | return me'type == PWHILE 247 | /method 248 | 249 | 250 | method PRoot.hasImported(name ptr uint8) bool 251 | mut i uintptr = 0 252 | mut len = me'imports.len() 253 | 254 | while i < len 255 | mut elem = (val me'imports.get(i)) 256 | 257 | if txt:strequals(elem'name, name) 258 | return true 259 | /if 260 | 261 | i++ 262 | /while 263 | 264 | return false 265 | /method 266 | 267 | 268 | method PModule.findDecl(name ptr uint8) ptr DeclInfo 269 | mut i uintptr = 0 270 | mut len = me'roots.len() 271 | 272 | while i < len 273 | mut root = (val me'roots.get(i)) 274 | 275 | if root'node'syms? 276 | mut declInfo = root'node'syms.get(name) 277 | if declInfo? 278 | return declInfo 279 | /if 280 | /if 281 | 282 | i++ 283 | /while 284 | 285 | return null 286 | /method 287 | 288 | 289 | method PModule.findSym(name ptr uint8) ptr Type 290 | mut i uintptr = 0 291 | mut len = me'roots.len() 292 | 293 | while i < len 294 | mut root = (val me'roots.get(i)) 295 | 296 | if root'node'syms? 297 | mut modSym = root'node'syms.typeof(name) 298 | if modSym? 299 | return modSym 300 | /if 301 | /if 302 | 303 | i++ 304 | /while 305 | 306 | return null 307 | /method 308 | 309 | 310 | func pmoduleFree(pmod ptr PModule) 311 | if pmod? 312 | mem:free(pmod'name) 313 | vect:freeAll(pmod'roots, (ptr pnodeFree)) 314 | 315 | mem:free(pmod) 316 | /if 317 | /func 318 | 319 | 320 | func pnodeFree(pnode ptr PNode) 321 | if pnode? 322 | if pnode.isRoot() 323 | 324 | mut proot = (pnode) 325 | strdefFree(proot'moduleName) 326 | mem:free(proot'fileName) 327 | list:freeAll(proot'imports, (ptr strdefFree)) 328 | stabFree(proot'aliases) 329 | 330 | memutils:fpFree(proot'typePool) 331 | /if 332 | 333 | if pnode.isDecl() 334 | 335 | mut pdecl = (pnode) 336 | memutils:decRef(pdecl'sym) 337 | 338 | mem:free(pdecl'methodTypeModule) 339 | mem:free(pdecl'methodType) 340 | 341 | /if 342 | 343 | if pnode.isBlock() 344 | stabFree((pnode)'syms) 345 | /if 346 | 347 | # remember to fix PBLOCK leaks. 348 | 349 | # remember to fix PEXPR leaks. 350 | 351 | list:freeAll(pnode'leaves, ptr pnodeFree) 352 | 353 | mem:free(pnode) 354 | /if 355 | /func 356 | 357 | 358 | mut PROOT uint16 = 10 359 | mut PENTRY uint16 = 20 360 | mut PFUNCTION uint16 = 30 361 | mut PALIAS uint16 = 40 362 | mut PMUT uint16 = 60 363 | mut PMUTEXP uint16 = 65 364 | mut PIF uint16 = 70 365 | mut PEXPR uint16 = 80 366 | mut PBREAK uint16 = 90 367 | mut PCONTINUE uint16 = 100 368 | mut PRETURN uint16 = 110 369 | mut PIFELSE uint16 = 120 370 | mut PWHILE uint16 = 130 371 | mut PBLOCK uint16 = 140 372 | mut PMETHOD uint16 = 150 373 | -------------------------------------------------------------------------------- /libforkparse/src/ast/issue.fork: -------------------------------------------------------------------------------- 1 | # libforkparse, a full parser for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module ast 12 | 13 | 14 | import err 15 | import list 16 | import mem 17 | import txt 18 | 19 | 20 | alias Issue struct ( 21 | gravity uint8, 22 | where txt:Line, 23 | filename,message ptr uint8 24 | ) 25 | 26 | 27 | alias Issues struct ( 28 | list list:List, 29 | errLen uintptr 30 | ) 31 | 32 | 33 | func issueFree(issue ptr Issue) 34 | if issue? 35 | mem:free(issue'filename) 36 | mem:free(issue'message) 37 | /if 38 | /func 39 | 40 | 41 | func issueNew(gravity uint8, where txt:Line, filename, message ptr uint8) ptr Issue 42 | mut issue = (mem:zalloc(size(Issue))) 43 | 44 | issue'gravity = gravity 45 | issue'where = where 46 | issue'filename = txt:strclone(filename) 47 | issue'message = txt:strclone(message) 48 | 49 | return issue 50 | /func 51 | 52 | 53 | func issueGravityToStr(issueGravity uint8) ptr uint8 54 | if issueGravity == ISSUE_ERR 55 | return "error" 56 | /if 57 | 58 | if issueGravity == ISSUE_WARN 59 | return "warning" 60 | /if 61 | 62 | if issueGravity == ISSUE_INFO 63 | return "info" 64 | /if 65 | 66 | return "" 67 | /func 68 | 69 | 70 | func issueToError(issue ptr Issue) ptr err:Error 71 | mut lineno [21] uint8 72 | mut pos [21] uint8 73 | 74 | txt:numtostr(issue'where'line, ptr lineno[0], 21) 75 | txt:numtostr(issue'where'pos, ptr pos[0], 21) 76 | 77 | mut toglue [10] ptr uint8 78 | toglue[0] = issue'filename 79 | toglue[1] = ":" 80 | toglue[2] = ptr lineno[0] 81 | toglue[3] = ":" 82 | toglue[4] = ptr pos[0] 83 | toglue[5] = ": " 84 | toglue[6] = issueGravityToStr(issue'gravity) 85 | toglue[7] = ": " 86 | toglue[8] = issue'message 87 | toglue[9] = null 88 | 89 | mut ret = err:glue(ptr toglue[0]) 90 | 91 | issueFree(issue) 92 | 93 | return ret 94 | /func 95 | 96 | 97 | method Issue.writeOut(outFn ptr func(err ptr uint8)) 98 | outFn(me'filename) 99 | outFn(":") 100 | 101 | 102 | mut buf [21] uint8 103 | txt:numtostr(me'where'line, ptr buf[0], 21) 104 | 105 | outFn(ptr buf[0]) 106 | outFn(":") 107 | 108 | txt:numtostr(me'where'pos, ptr buf[0], 21) 109 | 110 | outFn(ptr buf[0]) 111 | outFn(": ") 112 | 113 | outFn(issueGravityToStr(me'gravity)) 114 | outFn(": ") 115 | outFn(me'message) 116 | outFn("\n") 117 | /method 118 | 119 | 120 | # Issues container 121 | 122 | func issuesFree(iss ptr Issues) 123 | if iss? 124 | list:deinitAll(ptr iss'list, ptr issueFree) 125 | mem:free(iss) 126 | /if 127 | /func 128 | 129 | 130 | func issuesNew() ptr Issues 131 | mut iss = (mem:zalloc(size(Issues))) 132 | list:init(ptr iss'list) 133 | 134 | return iss 135 | /func 136 | 137 | 138 | method Issues.add(issue ptr Issue) 139 | if issue? 140 | me'list.append(issue) 141 | 142 | if issue'gravity == ISSUE_ERR 143 | me'errLen++ 144 | /if 145 | /if 146 | /method 147 | 148 | 149 | method Issues.addAll(i2 ptr Issues) 150 | me'list.appendList(ptr i2'list) 151 | 152 | me'errLen = me'errLen + i2'errLen 153 | 154 | i2'list.prune() 155 | /method 156 | 157 | 158 | method Issues.errLen() uintptr 159 | return me'errLen 160 | /method 161 | 162 | 163 | method Issues.error(where txt:Line, filename, message ptr uint8) 164 | me'list.append(issueNew(ISSUE_ERR, where, filename, message)) 165 | 166 | me'errLen++ 167 | /method 168 | 169 | 170 | method Issues.get(i uintptr) ptr Issue 171 | return (val me'list.get(i)) 172 | /method 173 | 174 | 175 | method Issues.len() uintptr 176 | return me'list.len() 177 | /method 178 | 179 | 180 | mut ISSUE_ERR uint8 = 10 181 | mut ISSUE_WARN uint8 = 20 182 | mut ISSUE_INFO uint8 = 30 183 | -------------------------------------------------------------------------------- /libforkparse/src/ast/psymbols.fork: -------------------------------------------------------------------------------- 1 | # libforkparse, a full parser for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module ast 12 | 13 | 14 | import list 15 | import memutils 16 | import txt 17 | 18 | 19 | # PType and PTypeDescr do not represent a type, but its parse-time representation. 20 | # Per example, uint16 and PType are bot "id-types", because they are syntactically presented by 21 | # an identifier at parsing time, while being really very different (a struct and an integer). 22 | 23 | alias PType struct ( 24 | refc memutils:Ref, 25 | name, moduleName ptr uint8, 26 | descr ptr PTypeDescr, 27 | begin, end txt:Line 28 | ) 29 | 30 | 31 | alias PTypeDescr struct ( 32 | refc memutils:Ref, 33 | type uint16, 34 | # if type is PTYPE_PTR or PTYPE_LOC, this is the type returned by dereferencing. 35 | # if type is PTYPE_FUNC, this is the return type of the function 36 | retType ptr PType, 37 | # if type is PTYPE_FUNC, this is the arguments list 38 | # if type is PTYPE_STRUCT, this is the fields list 39 | arguments ptr list:List, 40 | #if type is PTYPE_LOC, this is the number of items allocated 41 | length uintptr 42 | ) 43 | 44 | 45 | alias PSymbol struct( 46 | refc memutils:Ref, 47 | name ptr uint8, 48 | type ptr PType 49 | ) 50 | 51 | 52 | mut PTYPE_FUNC uint16 = 10 53 | mut PTYPE_ID uint16 = 20 54 | mut PTYPE_PTR uint16 = 30 55 | mut PTYPE_STRUCT uint16 = 40 56 | mut PTYPE_LOC uint16 = 50 57 | -------------------------------------------------------------------------------- /libforkparse/src/ast/symbols.fork: -------------------------------------------------------------------------------- 1 | # libforkparse, a full parser for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module ast 12 | 13 | 14 | import kv 15 | import map 16 | import mem 17 | import proc 18 | import tty 19 | import txt 20 | 21 | 22 | # Type represents a well formed, semantically valid type. 23 | # An instance of this is the product of type validation by sema. 24 | 25 | alias Type struct( 26 | # which type macroclass this instance represents. 27 | type uint16, 28 | 29 | # eventual alias (module and name) of the current type. 30 | moduleName, name ptr uint8, 31 | 32 | # if integer, this represent its signedness. 33 | isSigned bool, 34 | 35 | # size of this type. Set on creation. -1 if recursive. 36 | # functions have no size. 37 | # alignment of this type. Set on creation. -1 if recursive. 38 | typeSize, typeAlign intptr, 39 | 40 | # number of items, in case this is a location. 41 | itemCount uintptr, 42 | 43 | # the type the current instance evaluates to when an operation like function invocation or derefereciation is made. 44 | # For pointers, this is the type of the expression obtained with val. 45 | # For functions, this is the value of the expression obtained invoking the function. 46 | retType ptr Type, 47 | 48 | # The members that compose this type. 49 | # For functions, these are the parameters. 50 | # For structures, these are the members. 51 | members ptr kv:KVList, 52 | 53 | # if this type is builtin 54 | builtin bool, 55 | 56 | # where the original type was defined. 57 | begin, end txt:Line 58 | ) 59 | 60 | 61 | alias Symbol struct( 62 | name ptr uint8, 63 | type ptr Type 64 | ) 65 | 66 | 67 | alias DeclInfo struct( 68 | declType uint16, 69 | declOnly,funcParam bool, 70 | type ptr Type 71 | ) 72 | 73 | 74 | alias MethodInfo struct( 75 | typeModule,typeName,name ptr uint8, 76 | type ptr Type 77 | ) 78 | 79 | 80 | alias Symtable struct( 81 | syms ptr kv:KVList 82 | ) 83 | 84 | 85 | method Symbol.equals(other ptr Symbol) bool 86 | return txt:strequals(me'name, other'name) and me'type.equals(other'type) 87 | /method 88 | 89 | 90 | func typeEqualsList(list1, list2 ptr kv:KVList) bool 91 | mut len = list1.len() 92 | 93 | if len != list2.len() 94 | return false 95 | /if 96 | 97 | mut i uintptr = 0 98 | 99 | while i < len 100 | mut pair1 = list1.getAt(i) 101 | mut pair2 = list2.getAt(i) 102 | 103 | mut name1 = (pair1'key) 104 | mut name2 = (pair2'key) 105 | 106 | mut type1 = (pair1'value) 107 | mut type2 = (pair2'value) 108 | 109 | if not txt:strequals(name1, name2) or not type1.equals(type2) 110 | return false 111 | /if 112 | 113 | i++ 114 | /while 115 | 116 | return true 117 | /func 118 | 119 | 120 | func typeFree(type ptr Type) 121 | if type? 122 | mem:free(type'moduleName) 123 | mem:free(type'name) 124 | 125 | if type'members? 126 | kv:free(type'members) 127 | /if 128 | 129 | mem:free(type) 130 | /if 131 | /func 132 | 133 | 134 | method Type.equals(other ptr Type) bool 135 | if not other? 136 | return false 137 | /if 138 | 139 | if me'name? and other'name? 140 | mut res = txt:strequals(me'name, other'name) 141 | 142 | if res and me'moduleName? and other'moduleName? 143 | res = txt:strequals(me'moduleName, other'moduleName) 144 | /if 145 | 146 | return res 147 | /if 148 | 149 | if me'type != other'type 150 | return false 151 | /if 152 | 153 | if me'type == TYPE_FUNC 154 | return me'retType.equals(other'retType) and typeEqualsList(me'members, other'members) 155 | else 156 | if me'type == TYPE_PTR 157 | return me'retType.equals(other'retType) 158 | else 159 | if me'type == TYPE_STRUCT 160 | return typeEqualsList(me'members, other'members) 161 | else 162 | if me'type == TYPE_LOC 163 | return me'retType.equals(other'retType) and me'itemCount == other'itemCount 164 | else 165 | if me'type == TYPE_BOOL 166 | return true 167 | else 168 | if me'type == TYPE_INT 169 | return me'isSigned == other'isSigned and me'typeSize == other'typeSize 170 | else 171 | if me'type == TYPE_DATA 172 | return true 173 | else 174 | if me'type == TYPE_NULL 175 | return true 176 | else 177 | proc:panic("unreachable: unknown type comparison") 178 | /if 179 | /if 180 | /if 181 | /if 182 | /if 183 | /if 184 | /if 185 | /if 186 | /method 187 | 188 | 189 | method Type.isBool() bool 190 | return me'type == TYPE_BOOL 191 | /method 192 | 193 | 194 | method Type.isData() bool 195 | return me'type == TYPE_DATA 196 | /method 197 | 198 | 199 | method Type.isEmpty() bool 200 | return me'type == TYPE_EMPTY 201 | /method 202 | 203 | 204 | method Type.isFunc() bool 205 | return me'type == TYPE_FUNC 206 | /method 207 | 208 | 209 | method Type.isInt() bool 210 | return me'type == TYPE_INT 211 | /method 212 | 213 | 214 | method Type.isLoc() bool 215 | return me'type == TYPE_LOC 216 | /method 217 | 218 | 219 | method Type.isNull() bool 220 | return me'type == TYPE_NULL 221 | /method 222 | 223 | 224 | method Type.isPtr() bool 225 | return me'type == TYPE_PTR or me'type == TYPE_DATA 226 | /method 227 | 228 | 229 | method Type.isStruct() bool 230 | return me'type == TYPE_STRUCT 231 | /method 232 | 233 | 234 | func stabNew() ptr Symtable 235 | mut stab = (mem:zalloc(size(Symtable))) 236 | 237 | stab'syms = kv:strnew(10) 238 | 239 | stab'syms.setFreeFuncs(ptr mem:free, ptr declInfoFree) 240 | 241 | return stab 242 | /func 243 | 244 | 245 | func stabFree(stab ptr Symtable) 246 | if stab? 247 | kv:free(stab'syms) 248 | mem:free(stab) 249 | /if 250 | /func 251 | 252 | 253 | method Symtable.add(name ptr uint8, 254 | isDecl,funcParam bool, 255 | type ptr Type, 256 | symType uint16) 257 | 258 | me'syms.put(txt:strclone(name), \ 259 | declInfoNew(symType, isDecl, funcParam, type)) 260 | /method 261 | 262 | 263 | method Symtable.get(name ptr uint8) ptr DeclInfo 264 | return (me'syms.get(name)) 265 | /method 266 | 267 | 268 | method Symtable.typeof(name ptr uint8) ptr Type 269 | mut di = me.get(name) 270 | 271 | return di? => di'type || null 272 | /method 273 | 274 | 275 | mut TYPE_FUNC uint16 = 10 276 | mut TYPE_PTR uint16 = 20 277 | mut TYPE_STRUCT uint16 = 30 278 | mut TYPE_LOC uint16 = 40 279 | mut TYPE_BOOL uint16 = 50 280 | mut TYPE_INT uint16 = 60 281 | mut TYPE_DATA uint16 = 70 282 | mut TYPE_RECALIAS uint16 = 80 283 | mut TYPE_NULL uint16 = 90 284 | mut TYPE_EMPTY uint16 = 100 285 | -------------------------------------------------------------------------------- /libforkparse/src/ast/tokens.fork: -------------------------------------------------------------------------------- 1 | # libforkparse, a full parser for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module ast 12 | 13 | 14 | mut EOF uint16 = 0 15 | mut NEWLINE uint16 = 10 16 | mut ALIAS uint16 = 20 17 | mut BREAK uint16 = 70 18 | mut CAST uint16 = 80 19 | mut CBRAC uint16 = 90 20 | mut COLON uint16 = 100 21 | mut COMMA uint16 = 110 22 | mut CONTINUE uint16 = 120 23 | mut CCURLY uint16 = 125 24 | mut CPAR uint16 = 130 25 | mut DECL uint16 = 150 26 | mut ELSE uint16 = 180 27 | mut ENDENTRY uint16 = 190 28 | mut ENDFUNC uint16 = 200 29 | mut ENDIF uint16 = 210 30 | mut ENDMETHOD uint16 = 215 31 | mut ENDWHILE uint16 = 220 32 | mut ENTRY uint16 = 230 33 | mut FALSE uint16 = 240 34 | mut FUNC uint16 = 250 35 | mut ID uint16 = 260 36 | mut IF uint16 = 270 37 | mut IMPORT uint16 = 280 38 | mut METHOD uint16 = 310 39 | mut ME uint16 = 320 40 | mut MODULE uint16 = 360 41 | mut MUT uint16 = 370 42 | mut NULL uint16 = 380 43 | mut NUMBER uint16 = 390 44 | mut OCURLY uint16 = 420 45 | mut RETURN uint16 = 450 46 | mut SEPARATOR uint16 = 460 47 | mut SIZE uint16 = 490 48 | mut STRING uint16 = 500 49 | mut STRUCT uint16 = 520 50 | mut TRUE uint16 = 550 51 | mut WHILE uint16 = 560 52 | 53 | # Operator tokens. 54 | # The first two ciphers represent the priority; this can be 55 | # obtained using token / 1000. 56 | # Last cipher represents the operator type: 57 | # - 0 stands for binary, left associative 58 | # - 1 stands for binary, right associative 59 | # - 2 stands for unary, left associative 60 | # - 3 stands for unary, right associative 61 | 62 | mut TWOCOLONS uint16 = 17520 63 | 64 | mut APOS uint16 = 16050 65 | mut DEC uint16 = 16042 66 | mut DOT uint16 = 16060 67 | mut INC uint16 = 16092 68 | mut OPAR uint16 = 16411 69 | mut OBRAC uint16 = 16401 70 | mut QUEST uint16 = 16192 71 | 72 | mut MINUS uint16 = 15343 73 | mut NOT uint16 = 15383 74 | mut PTR uint16 = 15463 75 | mut UMINUS uint16 = 15353 76 | mut VAL uint16 = 15523 77 | 78 | mut POW uint16 = 14450 79 | 80 | mut DIV uint16 = 13170 81 | mut MOD uint16 = 13350 82 | mut TIMES uint16 = 13510 83 | 84 | mut PLUS uint16 = 12440 85 | 86 | mut SHIFTL uint16 = 11440 87 | mut SHIFTR uint16 = 11340 88 | 89 | mut MAJEQ uint16 = 10300 90 | mut MAJOR uint16 = 10310 91 | mut MINEQ uint16 = 10320 92 | mut MINOR uint16 = 10330 93 | 94 | mut DIFFERENT uint16 = 9160 95 | mut EQUAL uint16 = 9240 96 | 97 | mut AMPER uint16 = 8040 98 | 99 | mut XOR uint16 = 7550 100 | 101 | mut PIPE uint16 = 6420 102 | 103 | mut AND uint16 = 5040 104 | 105 | mut OR uint16 = 4420 106 | 107 | mut DQUEST uint16 = 3000 108 | 109 | mut FATARROW uint16 = 2061 110 | 111 | mut ASSIGN uint16 = 1061 112 | -------------------------------------------------------------------------------- /libforkparse/src/parser/dump.fork: -------------------------------------------------------------------------------- 1 | # libforkparse, a full parser for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module parser 12 | 13 | 14 | import map 15 | import pair 16 | import tty 17 | 18 | 19 | method Parser.dumpImports() 20 | mut iter = me'imports.iter() 21 | 22 | mut pair ptr pair:Pair 23 | 24 | tty:out("[") 25 | 26 | mut first = true 27 | 28 | while (pair = iter.next())? 29 | if first 30 | first = false 31 | else 32 | tty:out(", ") 33 | /if 34 | 35 | tty:out(cast(pair'key)) 36 | 37 | /while 38 | 39 | tty:outln("]") 40 | 41 | map:iterFree(iter) 42 | /method 43 | -------------------------------------------------------------------------------- /libforkparse/src/parser/parser.fork: -------------------------------------------------------------------------------- 1 | # libforkparse, a full parser for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module parser 12 | 13 | 14 | import ast 15 | import err 16 | import fs 17 | import list 18 | import map 19 | import mem 20 | import memutils 21 | import proc 22 | import set 23 | import tty 24 | import txt 25 | 26 | 27 | alias StringDefFile struct( 28 | text,fileName ptr uint8, 29 | begin,end txt:Line 30 | ) 31 | 32 | 33 | alias Parser struct ( 34 | fordPaths ptr list:List, 35 | imports ptr map:Map, 36 | importsTPool ptr memutils:FreePool, 37 | currentFile ptr uint8, 38 | builtins ptr map:Map 39 | ) 40 | 41 | 42 | # Parser init/deinit funcs 43 | 44 | func free(prs ptr Parser) 45 | if prs? 46 | map:free(prs'imports) 47 | memutils:fpFree(prs'importsTPool) 48 | list:freeAll(prs'fordPaths, ptr mem:free) 49 | 50 | map:free(prs'builtins) 51 | 52 | mem:free(prs'currentFile) 53 | mem:free(prs) 54 | /if 55 | /func 56 | 57 | 58 | func new() ptr Parser 59 | mut prs = (mem:zalloc(size(Parser))) 60 | prs'imports = map:strnew() 61 | prs'importsTPool = memutils:fpNew((ptr ast:typeFree)) 62 | 63 | prs'imports.setFreeFuncs(ptr mem:free, \ 64 | (ptr fordFree)) 65 | 66 | prs'fordPaths = envExtractFordPaths() 67 | prs'builtins = ast:builtinSetNew() 68 | return prs 69 | /func 70 | 71 | 72 | # Parser methods 73 | 74 | method Parser.getImport(name ptr uint8) ptr Ford 75 | return (me'imports.get(name)) 76 | /method 77 | 78 | 79 | method Parser.findFord(name ptr uint8) {ford ptr Ford, 80 | err ptr err:Error} 81 | 82 | mut ford = (me'imports.get(name)) 83 | 84 | if ford? 85 | return {ford,null} 86 | /if 87 | 88 | mut fordName = txt:strappend(name, ".ford") 89 | 90 | mut len = me'fordPaths.len() 91 | 92 | mut i uintptr = 0 93 | 94 | while i < len 95 | mut path = (val me'fordPaths.get(i)) 96 | mut joinedPath = fs:pathJoin(path, fordName) 97 | 98 | if fs:pathExists(joinedPath) 99 | 100 | mut {ford,err} = me.loadFord(joinedPath) 101 | 102 | mem:free(joinedPath) 103 | mem:free(fordName) 104 | 105 | if err? 106 | mut cs = txt:newCs(20) 107 | cs.add("can't load ") 108 | cs.add(joinedPath) 109 | cs.add(": ") 110 | cs.add(err.msg()) 111 | 112 | mut msg = txt:unwrapCs(cs) 113 | 114 | err:free(err) 115 | 116 | mut newErr = err:new(msg) 117 | 118 | mem:free(msg) 119 | 120 | return {null,newErr} 121 | /if 122 | 123 | me'imports.put(txt:strclone(name), ford) 124 | 125 | return {ford,null} 126 | /if 127 | 128 | mem:free(joinedPath) 129 | 130 | i++ 131 | /while 132 | 133 | 134 | mut toGlue [4] ptr uint8 135 | 136 | toGlue[0] = "Can't find " 137 | toGlue[1] = name 138 | toGlue[2] = " in the given FORDPATHS" 139 | toGlue[3] = null 140 | 141 | mut glued = txt:strglue(ptr toGlue[0]) 142 | 143 | mut err = err:new(glued) 144 | 145 | mem:free(fordName) 146 | mem:free(glued) 147 | 148 | return {null, err} 149 | /method 150 | 151 | 152 | method Parser.importMod(importName ptr StringDefFile) ptr ast:Issue 153 | mut {ford,err} = me.findFord(importName'text) 154 | if err? 155 | mut issue = ast:issueNew(ast:ISSUE_ERR, importName'begin, \ 156 | importName'fileName, err.msg()) 157 | 158 | err:free(err) 159 | 160 | return issue 161 | /if 162 | 163 | return null 164 | /method 165 | 166 | 167 | method Parser.importAll(imports ptr set:Set) ptr ast:Issues 168 | mut ret = ast:issuesNew() 169 | 170 | mut iter = imports.iter() 171 | mut el data 172 | 173 | while (el = iter.next())? 174 | mut importName = (el) 175 | mut issue = me.importMod(importName) 176 | 177 | if issue? 178 | ret.add(issue) 179 | /if 180 | /while 181 | 182 | return ret 183 | /method 184 | 185 | 186 | method Parser.matchBuiltin(name ptr uint8) ptr ast:Type 187 | return (me'builtins.get(name)) 188 | /method 189 | 190 | 191 | method Parser.parseDirectory(dirName ptr uint8) {pmod ptr ast:PModule, 192 | issues ptr ast:Issues} 193 | 194 | mut {pmod,issues} = parseModule(dirName) 195 | 196 | if issues.errLen() > 0 197 | return {null, issues} 198 | /if 199 | 200 | return {pmod, validateModuleAst(me, pmod)} 201 | 202 | /method 203 | 204 | 205 | method Parser.parseFile(fileName ptr uint8) {root ptr ast:PNode, 206 | issues ptr ast:Issues} 207 | 208 | mut {proot,err} = parse(fileName) 209 | 210 | if err? 211 | mut issues = ast:issuesNew() 212 | issues.add(err) 213 | 214 | return {null, issues} 215 | /if 216 | 217 | return {proot, validateAst(me, proot)} 218 | /method 219 | 220 | 221 | method Parser.setCurrentFile(filename ptr uint8) 222 | mem:free(me'currentFile) 223 | 224 | me'currentFile = txt:strclone(filename) 225 | /method 226 | 227 | 228 | func envExtractFordPaths() ptr list:List 229 | mut list = list:new() 230 | 231 | mut paths = proc:getenv("FORDPATHS") 232 | if paths? 233 | mut tkz = txt:tokenizerNew(paths, 58) #`:` 234 | mut path ptr uint8 235 | 236 | while (path = tkz.next())? 237 | list.append(path) 238 | /while 239 | 240 | /if 241 | 242 | return list 243 | /func 244 | -------------------------------------------------------------------------------- /libforkparse/src/parser/sema-base.fork: -------------------------------------------------------------------------------- 1 | # libforkparse, a full parser for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module parser 12 | 13 | 14 | import ast 15 | import hash 16 | import kv 17 | import list 18 | import mem 19 | import proc 20 | 21 | 22 | func intHash(n data) uintptr 23 | return (n) 24 | /func 25 | 26 | 27 | # This function validates a single declaration. 28 | # The resolver is used to resolve symbols and aliases; if they are in the global 29 | # scope, they may be unresolved yet, and are then verified. 30 | method Resolver.validatePDecl(pdecl ptr ast:PDecl) bool 31 | mut ntype = pdecl'node'type 32 | 33 | if ntype == ast:PMUT or ntype == ast:PFUNCTION or ntype == ast:PENTRY or ntype == ast:PMETHOD 34 | return me.registerTopDecl(pdecl)? 35 | else 36 | if ntype == ast:PALIAS 37 | return me.registerAlias(pdecl)? 38 | else 39 | proc:panic("unreachable: invalid pdecl value") 40 | /if 41 | /if 42 | 43 | # unreachable 44 | return false 45 | /method 46 | 47 | 48 | # This method validates a file AST. 49 | # Being supposed to be called by validateModuleFile, we may assume that all the 50 | # imports have been already evaluated. 51 | # 52 | # This function parses the children of the given AST root, using the resolver to 53 | # resolve eventual symbols and aliases. 54 | # 55 | # If not found, a symbol is looked after and verified out of order, allowing 56 | # complete visibility of the global module scope without any issue with the 57 | # declaration order of variables, aliases and functions. 58 | method Resolver.validateFile(root ptr ast:PRoot) bool 59 | 60 | if root'node'node'validated 61 | return true 62 | /if 63 | 64 | me.setCurrentRoot(root) 65 | 66 | mut pnode = (root) 67 | 68 | mut len = pnode'leaves.len() 69 | mut i uintptr = 0 70 | mut result = true 71 | 72 | while i < len 73 | mut node = (val pnode'leaves.get(i)) 74 | 75 | if node.isDecl() 76 | if not node'validated 77 | if not me.validatePDecl((node)) 78 | result = false 79 | 80 | break 81 | /if 82 | /if 83 | /if 84 | 85 | i++ 86 | /while 87 | 88 | return result 89 | /method 90 | 91 | 92 | method Resolver.validateModuleFile(root ptr ast:PRoot) 93 | mut proot = (root) 94 | me'prs.setCurrentFile(proot'fileName) 95 | 96 | me.validateFile(proot) 97 | /method 98 | 99 | 100 | func validateModuleAst(prs ptr Parser, pmod ptr ast:PModule) ptr ast:Issues 101 | mut iss = ast:issuesNew() 102 | 103 | mut rsv Resolver 104 | 105 | mut decls = rsv.collect(prs, pmod, iss) 106 | if not decls? 107 | return iss 108 | /if 109 | 110 | mut importIssues = prs.importAll(rsv'imports) 111 | mut importErrorsLen = importIssues.errLen() 112 | 113 | iss.addAll(importIssues) 114 | ast:issuesFree(importIssues) 115 | 116 | if importErrorsLen < 1 117 | mut i uintptr = 0 118 | mut len = pmod'roots.len() 119 | 120 | while i < len 121 | mut root = (val pmod'roots.get(i)) 122 | 123 | rsv.validateModuleFile(root) 124 | 125 | i++ 126 | /while 127 | 128 | kv:free(decls) 129 | resolverDeinit(ptr rsv) 130 | /if 131 | 132 | return iss 133 | /func 134 | 135 | 136 | func validateAst(prs ptr Parser, root ptr ast:PNode) ptr ast:Issues 137 | if not root.isRoot() 138 | proc:panic("non PRoot node can't be validated") 139 | return null 140 | /if 141 | 142 | mut pmod = ast:pmoduleNew() 143 | 144 | ast:pmoduleAdd(pmod, (root)) 145 | 146 | mut ret = validateModuleAst(prs, pmod) 147 | 148 | mem:free(pmod'name) 149 | mem:free(pmod) 150 | 151 | return ret 152 | /func 153 | -------------------------------------------------------------------------------- /libforkparse/src/parser/sema-resolver.fork: -------------------------------------------------------------------------------- 1 | # libforkparse, a full parser for the Fork language 2 | # Copyright (C) Marco Cilloni 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module parser 12 | 13 | 14 | import ast 15 | import kv 16 | import list 17 | import mem 18 | import memutils 19 | import proc 20 | import set 21 | import tty 22 | import txt 23 | 24 | 25 | func resolverDeinit(rsv ptr Resolver) 26 | kv:free(rsv'aliases) 27 | kv:free(rsv'decls) 28 | /func 29 | 30 | 31 | method Resolver.setCurrentRoot(root ptr ast:PRoot) 32 | me'curRoot = root 33 | /method 34 | 35 | 36 | method Resolver.collectAlias(pdecl ptr ast:PDecl, 37 | root ptr ast:PRoot) bool 38 | 39 | mut name = pdecl'sym'name 40 | 41 | if me'aliases.contains(name) 42 | 43 | mut cs = txt:newCs(20) 44 | cs.add("alias ") 45 | cs.add(name) 46 | cs.add(" is already defined") 47 | 48 | me'issues.error(pdecl'node'begin, root'fileName, txt:unwrapCs(cs)) 49 | 50 | return false 51 | /if 52 | 53 | me'aliases.put(name, pdecl) 54 | 55 | return true 56 | /method 57 | 58 | 59 | method Resolver.collectDecls(pdecl ptr ast:PDecl, 60 | root ptr ast:PRoot) bool 61 | 62 | mut name = ast:declKey(pdecl) 63 | mut existent = (me'decls.get(name)) 64 | 65 | if existent? 66 | mut cs = txt:newCs(20) 67 | cs.add("symbol ") 68 | cs.add(name) 69 | cs.add(" defined twice in current module") 70 | 71 | mut str = txt:unwrapCs(cs) 72 | me'issues.error(pdecl'node'begin, root'fileName, str) 73 | 74 | mem:free(str) 75 | mem:free(name) 76 | 77 | return false 78 | /if 79 | 80 | #search for method in module 81 | 82 | me'decls.put(name, pdecl) 83 | return true 84 | /method 85 | 86 | 87 | method Resolver.collectPDecl(pnode ptr ast:PNode, 88 | root ptr ast:PRoot, 89 | entryNode ptr ptr ast:PDecl) bool 90 | 91 | 92 | 93 | if pnode.isMulDecl() 94 | mut msg = "mut struct expansion is not allowed on global scope" 95 | me'issues.error(pnode'begin, root'fileName, msg) 96 | 97 | return false 98 | /if 99 | 100 | # Once we're sure that this isn't a multiple declaration, we are certain it 101 | # is a PDecl 102 | mut pdecl = (pnode) 103 | 104 | mut ntype = pdecl'node'type 105 | 106 | if ntype == ast:PMUT or ntype == ast:PFUNCTION or ntype == ast:PMETHOD 107 | if not me.collectDecls(pdecl, root) 108 | return false 109 | /if 110 | else 111 | 112 | if ntype == ast:PALIAS 113 | if not me.collectAlias(pdecl, root) 114 | return false 115 | /if 116 | else 117 | 118 | if ntype == ast:PENTRY 119 | if not (val entryNode)? 120 | val entryNode = pdecl 121 | else 122 | me'issues.error(pdecl'node'begin, root'fileName, \ 123 | "entry declared twice in same module") 124 | 125 | return false 126 | /if 127 | else 128 | proc:panic("unreachable: invalid pdecl value") 129 | /if 130 | /if 131 | /if 132 | 133 | return true 134 | /method 135 | 136 | 137 | method Resolver.collectImports(fileName ptr uint8, list ptr list:List) 138 | mut len = list.len() 139 | mut i uintptr = 0 140 | 141 | while i < len 142 | mut imp = cast(val list.get(i)) 143 | mut sdf = cast(mem:alloc(size(StringDefFile))) 144 | 145 | val sdf = {imp'name, fileName, imp'begin, imp'end} 146 | 147 | me'imports.put(sdf) 148 | 149 | i++ 150 | /while 151 | /method 152 | 153 | 154 | method Resolver.collectFromRoot(root ptr ast:PRoot, 155 | values ptr kv:KVList, 156 | entryNode ptr ptr ast:PDecl) bool 157 | 158 | me.collectImports(root'fileName, root'imports) 159 | 160 | mut len = root'node'node'leaves.len() 161 | mut i uintptr = 0 162 | 163 | while i < len 164 | mut pnode = (val root'node'node'leaves.get(i)) 165 | 166 | if not me.collectPDecl(pnode, root, entryNode) 167 | 168 | return false 169 | /if 170 | 171 | mut pdecl = (pnode) 172 | values.put(ast:declKey(pdecl), pdecl) 173 | 174 | i++ 175 | /while 176 | 177 | return true 178 | /method 179 | 180 | 181 | func sdfhash(sdf ptr StringDefFile) uintptr 182 | return txt:strhash(sdf'text) 183 | /func 184 | 185 | 186 | method Resolver.collect(prs ptr Parser, 187 | pmod ptr ast:PModule, 188 | issues ptr ast:Issues) ptr kv:KVList 189 | 190 | me'imports = set:new(5, ptr sdfhash) 191 | me'aliases = kv:strnew(5) 192 | me'decls = kv:strnew(10) 193 | me'issues = issues 194 | 195 | me'imports.setFreeFunc(ptr mem:free) 196 | 197 | me'prs = prs 198 | 199 | mut ret = kv:strnew(20) 200 | 201 | ret.setFreeFuncs(ptr mem:free, null) 202 | 203 | pmod'entryNode = null 204 | 205 | mut i uintptr = 0 206 | mut len = pmod'roots.len() 207 | 208 | while i < len 209 | mut root = (val pmod'roots.get(i)) 210 | 211 | # init the root file with type pool and aliases/decls symtable 212 | root'typePool = memutils:fpNew((ptr ast:typeFree)) 213 | root'aliases = ast:stabNew() 214 | root'node'syms = ast:stabNew() 215 | 216 | if not me.collectFromRoot(root, ret, (ptr pmod'entryNode)) 217 | kv:free(ret) 218 | 219 | return null 220 | /if 221 | 222 | i++ 223 | /while 224 | 225 | return ret 226 | /method 227 | -------------------------------------------------------------------------------- /libforkparse/src/parser/version.fork: -------------------------------------------------------------------------------- 1 | # libforkparse, a full parser for the Fork language 2 | # Copyright (C) Marco Cilloni 2014, 2015, 2016 3 | # 4 | # This Source Code Form is subject to the terms of the Mozilla Public 5 | # License, v. 2.0. If a copy of the MPL was not distributed with this 6 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | # Exhibit B is not attached; this software is compatible with the 8 | # licenses expressed under Section 1.12 of the MPL v2. 9 | 10 | 11 | module parser 12 | 13 | 14 | mut RELEASE uint16 = 13 15 | 16 | mut VER_MAJ uint8 = 0 17 | mut VER_MIN uint8 = 7 18 | mut VER_PATCH uint8 = 1 19 | 20 | mut VERSION = "0.7.1" 21 | -------------------------------------------------------------------------------- /syntax/atom/grammars/fork.cson: -------------------------------------------------------------------------------- 1 | 'scopeName': 'source.fork' 2 | 'fileTypes': [ 3 | 'fork' 4 | ] 5 | 'name': 'Fork', 6 | 'patterns': [ 7 | { 8 | 'include': '#comments' 9 | } 10 | { 11 | 'include': '#fork_function_call' 12 | } 13 | { 14 | 'match': '\\b(alias|break|continue|else|entry|func|if|import|method|module|return|while)\\b|(\\/entry|\\/func|\\/method|\\/if|\\/while)\\b' 15 | "name": "keyword.control.c" 16 | } 17 | { 18 | "match": "\\b(decl|mut)\\b" 19 | "name": "keyword.go" 20 | } 21 | { 22 | "match": "\\b(bool|data|int8|int16|int32|int64|intptr|uint8|uint16|uint32|uint64|uintptr|struct)\\b" 23 | "name": "storage.type.c" 24 | } 25 | { 26 | "match": "\\b(ptr|val)\\b" 27 | "name": "storage.modifier.c" 28 | } 29 | { 30 | "match": "\\b(and|cast|mod|not|or|sh<|sh>|size)\\b" 31 | "name": "keyword.control.c" 32 | } 33 | { 34 | "match": "\\b(null|true|false|me)\\b" 35 | "name": "constant.language.c++" 36 | } 37 | { 38 | "match": "\\b((0x[0-9a-fA-F]*)|(0o[0-7]*)|(0b[0|1]*)|(([0-9]+\\.?[0-9]*)|(\\.[0-9]+))((e|E)(\\+|-)?[0-9]+)?)(L|l|UL|ul|u|U|F|f|ll|LL|ull|ULL)?\\b" 39 | "name": "constant.numeric.c" 40 | } 41 | { 42 | "match": "^func\\s+([a-zA-Z0-9]*)\\s*\\(" 43 | "name": "meta.function.c" 44 | } 45 | { 46 | "begin": "\"" 47 | "beginCaptures": { 48 | "0": { 49 | "name": "punctuation.definition.string.begin.c" 50 | } 51 | } 52 | "end": "\"" 53 | "endCaptures": { 54 | "0": { 55 | "name": "punctuation.definition.string.end.c" 56 | } 57 | }, 58 | "name": "string.quoted.double.c" 59 | "patterns": [ 60 | { 61 | "include": "#string_escaped_char" 62 | } 63 | ] 64 | } 65 | ] 66 | "repository": { 67 | "comments": { 68 | "patterns": [ 69 | { 70 | "captures": { 71 | "1": { 72 | "name": "meta.toc-list.banner.line.c" 73 | } 74 | } 75 | "match": "^# =(\\s*.*?)\\s*=\\s*$\\n?" 76 | "name": "comment.line.banner.c++" 77 | } 78 | { 79 | 'begin': '(^[ \\t]+)?(?=#)' 80 | 'beginCaptures': 81 | '1': 82 | 'name': 'punctuation.whitespace.comment.leading.c++' 83 | 'end': '(?!\\G)' 84 | 'patterns': [ 85 | { 86 | 'begin': '#' 87 | 'beginCaptures': 88 | '0': 89 | 'name': 'punctuation.definition.comment.c++' 90 | 'end': '\\n' 91 | 'name': 'comment.line.double-slash.c++' 92 | 'patterns': [ 93 | { 94 | 'match': '(?>\\\\\\s*\\n)' 95 | 'name': 'punctuation.separator.continuation.c++' 96 | } 97 | ] 98 | } 99 | ] 100 | } 101 | ] 102 | } 103 | "string_escaped_char": { 104 | "patterns": [ 105 | { 106 | "match": "\\\\(\\\\|[abefnprtv'\"?]|[0-3]\\d{,2}|[4-7]\\d?|x[a-fA-F0-9]{,2}|u[a-fA-F0-9]{,4}|U[a-fA-F0-9]{,8})", 107 | "name": "constant.character.escape.c" 108 | }, 109 | { 110 | "match": "\\\\.", 111 | "name": "invalid.illegal.unknown-escape.c" 112 | } 113 | ] 114 | } 115 | "fork_function_call": { 116 | "captures": { 117 | "1": { 118 | "name": "punctuation.whitespace.function-call.leading.c" 119 | }, 120 | "2": { 121 | "name": "entity.name.function.c" 122 | }, 123 | "3": { 124 | "name": "punctuation.definition.parameters.c" 125 | } 126 | }, 127 | "match": "(?x) (?: (?= \\s ) (?:(?<=else|return) | (? 2 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | alias 12 | break 13 | continue 14 | decl 15 | else 16 | entry 17 | func 18 | if 19 | import 20 | module 21 | return 22 | select 23 | struct 24 | type 25 | var 26 | while 27 | /entry 28 | /func 29 | /if 30 | 31 | /while 32 | 33 | 34 | bool 35 | int8 36 | int16 37 | int32 38 | int64 39 | uintptr 40 | uint8 41 | uint16 42 | uint32 43 | uint64 44 | 45 | 46 | and 47 | or 48 | ptr 49 | val 50 | 51 | 52 | false 53 | null 54 | true 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /syntax/vscode/forklang-vscode/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to the "forklang-vscode" extension will be documented in this file. 3 | 4 | Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. 5 | 6 | ## [Unreleased] 7 | - Initial release -------------------------------------------------------------------------------- /syntax/vscode/forklang-vscode/README.md: -------------------------------------------------------------------------------- 1 | # forklang-vscode README 2 | 3 | This is the README for your extension "forklang-vscode". After writing up a brief description, we recommend including the following sections. 4 | 5 | ## Features 6 | 7 | Describe specific features of your extension including screenshots of your extension in action. Image paths are relative to this README file. 8 | 9 | For example if there is an image subfolder under your extension project workspace: 10 | 11 | \!\[feature X\]\(images/feature-x.png\) 12 | 13 | > Tip: Many popular extensions utilize animations. This is an excellent way to show off your extension! We recommend short, focused animations that are easy to follow. 14 | 15 | ## Requirements 16 | 17 | If you have any requirements or dependencies, add a section describing those and how to install and configure them. 18 | 19 | ## Extension Settings 20 | 21 | Include if your extension adds any VS Code settings through the `contributes.configuration` extension point. 22 | 23 | For example: 24 | 25 | This extension contributes the following settings: 26 | 27 | * `myExtension.enable`: enable/disable this extension 28 | * `myExtension.thing`: set to `blah` to do something 29 | 30 | ## Known Issues 31 | 32 | Calling out known issues can help limit users opening duplicate issues against your extension. 33 | 34 | ## Release Notes 35 | 36 | Users appreciate release notes as you update your extension. 37 | 38 | ### 1.0.0 39 | 40 | Initial release of ... 41 | 42 | ### 1.0.1 43 | 44 | Fixed issue #. 45 | 46 | ### 1.1.0 47 | 48 | Added features X, Y, and Z. 49 | 50 | ----------------------------------------------------------------------------------------------------------- 51 | 52 | ## Working with Markdown 53 | 54 | **Note:** You can author your README using Visual Studio Code. Here are some useful editor keyboard shortcuts: 55 | 56 | * Split the editor (`Cmd+\` on OSX or `Ctrl+\` on Windows and Linux) 57 | * Toggle preview (`Shift+CMD+V` on OSX or `Shift+Ctrl+V` on Windows and Linux) 58 | * Press `Ctrl+Space` (Windows, Linux) or `Cmd+Space` (OSX) to see a list of Markdown snippets 59 | 60 | ### For more information 61 | 62 | * [Visual Studio Code's Markdown Support](http://code.visualstudio.com/docs/languages/markdown) 63 | * [Markdown Syntax Reference](https://help.github.com/articles/markdown-basics/) 64 | 65 | **Enjoy!** -------------------------------------------------------------------------------- /syntax/vscode/forklang-vscode/language-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | // symbol used for single line comment. Remove this entry if your language does not support line comments 4 | "lineComment": "//", 5 | // symbols used for start and end a block comment. Remove this entry if your language does not support block comments 6 | "blockComment": [ "/*", "*/" ] 7 | }, 8 | // symbols used as brackets 9 | "brackets": [ 10 | ["{", "}"], 11 | ["[", "]"], 12 | ["(", ")"] 13 | ], 14 | // symbols that are auto closed when typing 15 | "autoClosingPairs": [ 16 | ["{", "}"], 17 | ["[", "]"], 18 | ["(", ")"], 19 | ["\"", "\""], 20 | ["'", "'"] 21 | ], 22 | // symbols that that can be used to surround a selection 23 | "surroundingPairs": [ 24 | ["{", "}"], 25 | ["[", "]"], 26 | ["(", ")"], 27 | ["\"", "\""], 28 | ["'", "'"] 29 | ] 30 | } -------------------------------------------------------------------------------- /syntax/vscode/forklang-vscode/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "forklang-vscode", 3 | "displayName": "forklang-vscode", 4 | "description": "Fork support for VS Code (Syntax only)", 5 | "version": "0.0.1", 6 | "publisher": "mcilloni", 7 | "engines": { 8 | "vscode": "^1.12.0" 9 | }, 10 | "categories": [ 11 | "Languages" 12 | ], 13 | "contributes": { 14 | "languages": [{ 15 | "id": "fork", 16 | "aliases": ["Fork", "fork"], 17 | "extensions": [".fork"], 18 | "configuration": "./language-configuration.json" 19 | }], 20 | "grammars": [{ 21 | "language": "fork", 22 | "scopeName": "source.fork", 23 | "path": "./syntaxes/fork.tmLanguage.json" 24 | }] 25 | } 26 | } -------------------------------------------------------------------------------- /syntax/vscode/forklang-vscode/syntaxes/fork.tmLanguage.json: -------------------------------------------------------------------------------- 1 | { 2 | "scopeName": "source.fork", 3 | "fileTypes": [ 4 | "fork" 5 | ], 6 | "name": "Fork", 7 | "patterns": [ 8 | { 9 | "include": "#comments" 10 | }, 11 | { 12 | "include": "#fork_function_call" 13 | }, 14 | { 15 | "match": "\\b(alias|break|continue|else|entry|func|if|import|method|module|return|while)\\b|(\\/entry|\\/func|\\/method|\\/if|\\/while)\\b", 16 | "name": "keyword.control.c" 17 | }, 18 | { 19 | "match": "\\b(decl|mut)\\b", 20 | "name": "keyword.go" 21 | }, 22 | { 23 | "match": "\\b(bool|data|int8|int16|int32|int64|intptr|uint8|uint16|uint32|uint64|uintptr|struct)\\b", 24 | "name": "storage.type.c" 25 | }, 26 | { 27 | "match": "\\b(ptr|val)\\b", 28 | "name": "storage.modifier.c" 29 | }, 30 | { 31 | "match": "\\b(and|cast|mod|not|or|sh<|sh>|size)\\b", 32 | "name": "keyword.control.c" 33 | }, 34 | { 35 | "match": "\\b(null|true|false|me)\\b", 36 | "name": "constant.language.c++" 37 | }, 38 | { 39 | "match": "\\b((0x[0-9a-fA-F]*)|(0o[0-7]*)|(0b[0|1]*)|(([0-9]+\\.?[0-9]*)|(\\.[0-9]+))((e|E)(\\+|-)?[0-9]+)?)(L|l|UL|ul|u|U|F|f|ll|LL|ull|ULL)?\\b", 40 | "name": "constant.numeric.c" 41 | }, 42 | { 43 | "match": "^func\\s+([a-zA-Z0-9]*)\\s*\\(", 44 | "name": "meta.function.c" 45 | }, 46 | { 47 | "begin": "\"", 48 | "beginCaptures": { 49 | "0": { 50 | "name": "punctuation.definition.string.begin.c" 51 | } 52 | }, 53 | "end": "\"", 54 | "endCaptures": { 55 | "0": { 56 | "name": "punctuation.definition.string.end.c" 57 | } 58 | }, 59 | "name": "string.quoted.double.c", 60 | "patterns": [ 61 | { 62 | "include": "#string_escaped_char" 63 | } 64 | ] 65 | } 66 | ], 67 | "repository": { 68 | "comments": { 69 | "patterns": [ 70 | { 71 | "captures": { 72 | "1": { 73 | "name": "meta.toc-list.banner.line.c" 74 | } 75 | }, 76 | "match": "^# =(\\s*.*?)\\s*=\\s*$\\n?", 77 | "name": "comment.line.banner.c++" 78 | }, 79 | { 80 | "begin": "(^[ \\t]+)?(?=#)", 81 | "beginCaptures": { 82 | "1": { 83 | "name": "punctuation.whitespace.comment.leading.c++" 84 | } 85 | }, 86 | "end": "(?!\\G)", 87 | "patterns": [ 88 | { 89 | "begin": "#", 90 | "beginCaptures": { 91 | "0": { 92 | "name": "punctuation.definition.comment.c++" 93 | } 94 | }, 95 | "end": "\\n", 96 | "name": "comment.line.double-slash.c++", 97 | "patterns": [ 98 | { 99 | "match": "(?>\\\\\\s*\\n)", 100 | "name": "punctuation.separator.continuation.c++" 101 | } 102 | ] 103 | } 104 | ] 105 | } 106 | ] 107 | }, 108 | "string_escaped_char": { 109 | "patterns": [ 110 | { 111 | "match": "\\\\(\\\\|[abefnprtv'\"?]|[0-3]\\d{,2}|[4-7]\\d?|x[a-fA-F0-9]{,2}|u[a-fA-F0-9]{,4}|U[a-fA-F0-9]{,8})", 112 | "name": "constant.character.escape.c" 113 | }, 114 | { 115 | "match": "\\\\.", 116 | "name": "invalid.illegal.unknown-escape.c" 117 | } 118 | ] 119 | }, 120 | "fork_function_call": { 121 | "captures": { 122 | "1": { 123 | "name": "punctuation.whitespace.function-call.leading.c" 124 | }, 125 | "2": { 126 | "name": "entity.name.function.c" 127 | }, 128 | "3": { 129 | "name": "punctuation.definition.parameters.c" 130 | } 131 | }, 132 | "match": "(?x) (?: (?= \\s ) (?:(?<=else|return) | (?/.vscode/extensions` folder and restart Code. 27 | * To share your extension with the world, read on https://code.visualstudio.com/docs about publishing an extension. -------------------------------------------------------------------------------- /tools/forktree/parsedir.fork: -------------------------------------------------------------------------------- 1 | # Copyright (C) Marco Cilloni 2015, 2016 2 | # 3 | # This Source Code Form is subject to the terms of the Mozilla Public 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this 5 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | # Exhibit B is not attached; this software is compatible with the 7 | # licenses expressed under Section 1.12 of the MPL v2. 8 | 9 | 10 | import ast 11 | import kv 12 | import list 13 | import map 14 | import mem 15 | import pair 16 | import parser 17 | import proc 18 | import tty 19 | import txt 20 | 21 | 22 | entry 23 | mut argv = proc:args() 24 | if argv'len != 1 25 | tty:errln("Wrong number of arguments, required: 1") 26 | proc:exit(1) 27 | /if 28 | 29 | mut prs = parser:new() 30 | mut {pmod,issues} = prs.parseDirectory(argv'args[0]) 31 | 32 | mut issLen = issues.len() 33 | 34 | if issLen > 0 35 | mut i uintptr = 0 36 | 37 | while i < issLen 38 | mut issue = issues.get(i) 39 | 40 | issue.writeOut(ptr tty:out) 41 | 42 | i++ 43 | /while 44 | 45 | ast:issuesFree(issues) 46 | proc:exit(1) 47 | /if 48 | 49 | mut i uintptr = 0 50 | mut len = pmod'roots.len() 51 | 52 | tty:out("#### MODULE ") 53 | tty:out(pmod'name ?? "
") 54 | tty:out("\n\n\n") 55 | 56 | tty:out("== IMPORTS: ") 57 | tty:outint(prs'imports.len()) 58 | tty:outch(10) 59 | 60 | mut iter = prs'imports.iter() 61 | 62 | mut pair ptr pair:Pair 63 | 64 | while (pair = iter.next())? 65 | tty:out("Imported ") 66 | tty:outln((pair'key)) 67 | 68 | pair:free(pair) 69 | /while 70 | 71 | map:iterFree(iter) 72 | 73 | 74 | while i < len 75 | mut root = (val pmod'roots.get(i)) 76 | 77 | tty:out("\n\n## FILE: ") 78 | tty:out(root'fileName) 79 | tty:outln("") 80 | 81 | mut aliases = root'aliases'syms 82 | 83 | tty:out("\n== ALIASES: ") 84 | tty:outint(aliases.len()) 85 | tty:outch(10) 86 | 87 | mut j uintptr = 0 88 | mut len = aliases.len() 89 | 90 | while j < len 91 | pair = aliases.getAt(j) 92 | tty:out("alias ") 93 | tty:outln((pair'key)) 94 | 95 | j++ 96 | /while 97 | 98 | mut decls = root'node'syms'syms 99 | 100 | tty:out("\n\n== DECLS: ") 101 | tty:outint(decls.len()) 102 | tty:outch(10) 103 | 104 | j = 0 105 | len = decls.len() 106 | 107 | while j < len 108 | pair = decls.getAt(j) 109 | mut dinfo = (pair'value) 110 | mut typeStr ptr uint8 = null 111 | 112 | if dinfo'declOnly 113 | tty:out("decl ") 114 | /if 115 | 116 | if dinfo'declType == ast:PFUNCTION 117 | typeStr = "func " 118 | else 119 | if dinfo'declType == ast:PENTRY 120 | typeStr = "entry " 121 | else 122 | if dinfo'declType == ast:PMETHOD 123 | typeStr = "method " 124 | else 125 | typeStr = "mut " 126 | /if 127 | /if 128 | /if 129 | 130 | tty:out(typeStr) 131 | tty:out((pair'key)) 132 | 133 | tty:out(" :: ") 134 | 135 | mut cs = txt:newCs(10) 136 | dinfo'type.summarize(cs) 137 | 138 | mut des = txt:unwrapCs(cs) 139 | 140 | tty:outln(des) 141 | 142 | mem:free(des) 143 | 144 | j++ 145 | /while 146 | 147 | i++ 148 | /while 149 | 150 | tty:out("\n\n==> Has entry? ") 151 | 152 | tty:outln(pmod'entryNode? => "yes" || "no") 153 | 154 | parser:free(prs) 155 | 156 | ast:pmoduleFree(pmod) 157 | /entry 158 | -------------------------------------------------------------------------------- /tools/transmod/transmod.fork: -------------------------------------------------------------------------------- 1 | # Copyright (C) Marco Cilloni 2016 2 | # 3 | # This Source Code Form is subject to the terms of the Mozilla Public 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this 5 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 | # Exhibit B is not attached; this software is compatible with the 7 | # licenses expressed under Section 1.12 of the MPL v2. 8 | 9 | 10 | import args 11 | import ast 12 | import ctrans 13 | import err 14 | import fs 15 | import io 16 | import mem 17 | import parser 18 | import proc 19 | import tty 20 | import txt 21 | 22 | 23 | func check(err ptr err:Error) 24 | if err? 25 | tty:err("error: ") 26 | tty:failln(err.msg()) 27 | /if 28 | /func 29 | 30 | 31 | entry 32 | mut args = args:new("translates a module") 33 | 34 | args.newFlag(args:STRING, "fpath", "directory to output ford (default: $PWD)", \ 35 | "PATH", false, false, "--ford", "-fo") 36 | args.newFlag(args:STRING, "cpath", "directory to output C file (default: $PWD)", \ 37 | "PATH", false, false, "--cfile", "-co") 38 | args.newFlag(args:STRING, "outname", "name to use for output files (default: inferred)", \ 39 | "NAME", false, false, "--outname", "-n") 40 | 41 | args.unboundsOpts("MODULEDIR", true, true) 42 | 43 | check(args.parse()) 44 | 45 | mut dir = cast(val args.getUnbounds().get(0)) 46 | 47 | mut prs = parser:new() 48 | 49 | mut {pmod,issues} = prs.parseDirectory(dir) 50 | 51 | mut issLen = issues.len() 52 | 53 | if issLen > 0 54 | mut i uintptr = 0 55 | 56 | while i < issLen 57 | mut issue = issues.get(i) 58 | 59 | issue.writeOut(ptr tty:out) 60 | 61 | i++ 62 | /while 63 | 64 | ast:issuesFree(issues) 65 | proc:exit(1) 66 | /if 67 | 68 | mut tr ctrans:Transl 69 | 70 | ctrans:init(ptr tr, pmod'name, prs) 71 | 72 | tr.translateModule(pmod) 73 | 74 | mut {head,cfile} = tr.dump() 75 | 76 | mut {ok,cpath} = args.getStr("cpath") 77 | mut {ok,outname} = args.getStr("outname") 78 | 79 | mut cname = txt:strappend(outname ?? pmod'name ?? "main", ".c") 80 | mut pwd = proc:getenv("PWD") 81 | 82 | mut cfilePath = fs:pathJoin(cpath ?? pwd, cname) 83 | 84 | mut {cstr,err} = fs:fileCreate(cfilePath) 85 | 86 | mem:free(cname) 87 | mem:free(cfilePath) 88 | 89 | check(err) 90 | 91 | cstr.writeStr(cfile) 92 | 93 | check(cstr.error()) 94 | 95 | io:streamClose(cstr) 96 | 97 | if pmod'name? 98 | mut fordBuf = parser:makeFord(pmod) 99 | 100 | mut {ok,fpath} = args.getStr("fpath") 101 | 102 | check(parser:writeFord(outname ?? pmod'name, fpath ?? pwd, fordBuf, head, txt:strlen(head))) 103 | /if 104 | 105 | ast:pmoduleFree(pmod) 106 | mem:free(cfile) 107 | mem:free(head) 108 | parser:free(prs) 109 | /entry 110 | --------------------------------------------------------------------------------