Files

gsc.src
  • // GreyScript Compiler (gsc)
  • // This program is self-hosting. THE FIRST TIME YOU COMPILE, however, you will
  • // need to insert an import code directive with the absolute path to Util.src
  • // If the first file specified for building contains "// @import" then the built
  • // binary will be importable irrespective of passed arguments.
  • // @dep:Util.src
  • // @import
  • // To use this as a library, create a Globals.src and set GSC_STANDALONE.
  • // Your main script should FIRST depend on Globals.src and secondly on gsc.
  • // The global object "GsCompiler" will be available to you.
  • if not globals.hasIndex("GSC_STANDALONE") then globals.GSC_STANDALONE = true
  • if GSC_STANDALONE and params.len == 0 then exit("Nothing to compile")
  • __scope = function()
  • absPath = function(path)
  • if path[0] == "/" then return path
  • if path == "." then return current_path
  • if path == ".." then return get_shell.host_computer.File(current_path).parent_path
  • return current_path + "/" + path
  • end function
  • Dep = {}
  • Dep._shl = get_shell
  • Dep._comp = Dep._shl.host_computer
  • Dep.build = function(files, depList = null)
  • if depList == null then depList = {}
  • ret = self._build(files.pull, depList)
  • files.forEach function(file)
  • ret._subDeps.push(outer.self._build(file, outer.depList))
  • end function
  • errors = ret._get_errors
  • if errors then return errors
  • return ret
  • end function
  • Dep._build = function(file, depList)
  • ret = new self
  • ret._depList = depList
  • ret._subDeps = []
  • ret._file = absPath(file)
  • ret._depList[ret._file] = true
  • ret._error = ret._process
  • return ret
  • end function
  • Dep._get_errors = function(self)
  • return self._error + self._subDeps.flatMap(@self._get_errors).join("")
  • end function
  • Dep.filterStr = function(str)
  • return str.indexOf("// @dep:") == 0 or str.indexOf("//@dep:") == 0
  • end function
  • Dep.mapDeps = function(str)
  • return str.split("@dep:")[1].trim
  • end function
  • Dep.toSubDep = function(self, str)
  • return self._build(str, self._depList)
  • end function
  • Dep.makeCurry = function(toCurry)
  • self = self
  • ret = function(obj)
  • return toCurry(outer.self, obj)
  • end function
  • return @ret
  • end function
  • Dep._process = function()
  • file = self._comp.File(self._file)
  • if not file then return "Unable to open " + self._file + "\n"
  • if file.is_binary then return ""
  • self._subDeps = file.get_content.
  • split(char(10)).
  • filter(@self.filterStr).
  • map(@self.mapDeps).
  • map(self.makeCurry(@self.toSubDep))
  • return ""
  • end function
  • Dep._collect = function(self)
  • return self._subDeps.flatMap(@self._collect) + [self._file]
  • end function
  • Dep.collect = function(self)
  • return self._collect.unique
  • end function
  • Builder = {}
  • Builder._shl = Dep._shl
  • Builder._comp = Dep._shl.host_computer
  • Builder.makeStr = function(str)
  • // GreyHack is stupid, this is required.
  • return "import" + "_code(""" + str + """)"
  • end function
  • Builder.init = function(files, outFile, stdout = null)
  • ret = new self
  • if not stdout then stdout = @print
  • ret._import = self._comp.File(files[0]).
  • get_content.
  • split(char(10)).
  • findOrElse("// @import", "").
  • indexOf("// @import") == 0
  • ret._root = Dep.build(files)
  • if not ret._root isa Dep then return ret._root
  • out = absPath(outFile).split("/")
  • ret._outDir = out[:-1].join("/")
  • ret._outName = out[-1]
  • ret._stdout = @stdout
  • s = "Compiling "
  • if ret._import then s = s + "importable "
  • stdout s + "to: " + ret._outDir + "/" + ret._outName
  • return ret
  • end function
  • Builder.compile = function(allowImport, verbose, keepTempFile)
  • depStrs = self._root.collect
  • if not self._comp.touch(current_path, "__mscTemp.src") then exit("Unable to create temp file. No permissions?")
  • tmpFile = self._comp.File(current_path + "/__mscTemp.src")
  • if verbose then depStrs.forEach(@self._stdout)
  • tmpFile.set_content depStrs.map(@self.makeStr).join(char(10))
  • ret = self._shl.build(tmpFile.path, current_path, allowImport or self._import)
  • if not keepTempFile then tmpFile.delete
  • bin = self._comp.File(current_path + "/__mscTemp")
  • if bin then bin.move(self._outDir, self._outName)
  • return ret
  • end function
  • ArgP = {}
  • ArgP.verbose = false
  • ArgP.keepTempFile = false
  • ArgP.allowImport = false
  • ArgP["-h"] = function()
  • print "GreyScript Compiler - v0.1.0\n"
  • print "Designed to support nested permissions. Instead of using import code."
  • print "You should place (for example) ""// @dep:MyDep.src"" somewhere in your code.\n"
  • print "<b>Relative paths in source code must match where you run this compiler.</b>"
  • print "Argument format: msc [-t/--keep-temp-file] [-v/--verbose] [-i/--importable] file.src... [OUTFILE]\n"
  • print "-t: Keep the __mscTemp file that is generated in the working dir when compiling."
  • print "-v: Write the dependency chain to the terminal. This should match the temp file.\n"
  • print "-i: Make the generated binary importable. This is also true if the first source file"
  • print " that you pass contains ""// @import"" anywhere in the file. Other files are ignored."
  • print "-h: Print this help info"
  • exit "If you do not supply an output file name, it will default to the first source file's name"
  • end function
  • ArgP["--help"] = @ArgP["-h"]
  • ArgP["-t"] = function()
  • self.keepTempFile = true
  • end function
  • ArgP["--keep-temp-file"] = @ArgP["-t"]
  • ArgP["-v"] = function()
  • self.verbose = true
  • end function
  • ArgP["--verbose"] = @ArgP["-v"]
  • ArgP["-i"] = function()
  • self.allowImport = true
  • end function
  • ArgP["--importable"] = @ArgP["-i"]
  • ArgP.tocwd = function(path)
  • return current_path + "/" + path.split("/")[-1]
  • end function
  • ArgP.main = function()
  • while params.len > 0 and params[0][0] == "-"
  • arg = params.pull
  • if self.hasIndex(arg) then self[arg]()
  • end while
  • src_files = function(s)
  • return s.indexOf(".src") != null
  • end function
  • not_file = function(s); return not src_files(s); end function
  • files = params.filter(@src_files)
  • outFile = params.findOrElse(@not_file, self.tocwd(files[0].replace(".src", "")))
  • b = Builder.init(files, outFile)
  • if not b isa Builder then return print(b + "Compilation failed")
  • err = b.compile(self.allowImport, self.verbose, self.keepTempFile)
  • if err then print(err)
  • end function
  • if GSC_STANDALONE then ArgP.main()
  • return Builder
  • end function // end scope
  • globals.GsCompiler = __scope
Util.src
  • if not globals.hasIndex("UTIL_DEFINED") then
  • list.flatten = function()
  • t = null
  • ret = null
  • if self isa list then
  • t = list
  • ret = []
  • else if self isa map then
  • t = map
  • ret = {}
  • end if
  • for i in self
  • if @i isa t then ret = ret + i.flatten
  • if not @i isa t then ret.push(@i)
  • end for
  • return ret
  • end function
  • map.flatten = @list.flatten
  • list.flatMap = function(func, inst = null)
  • t = null
  • ret = null
  • if self isa list then
  • t = list
  • ret = []
  • else if self isa map then
  • t = map
  • ret = {}
  • end if
  • for i in self.indexes
  • obj = funcRef.invoke(@func, self[@i], inst)
  • if @obj isa t then ret = ret + obj.flatten
  • if not @obj isa t then ret.push(@obj)
  • end for
  • return ret
  • end function
  • map.flatMap = @list.flatMap
  • list.filter = function(func, inst = null)
  • ret = null
  • if self isa list then ret = []
  • if self isa map then ret = {}
  • for i in self.indexes
  • if not funcRef.invoke(@func, @self[@i], @inst) then continue
  • if ret isa list then ret.push(self[@i])
  • if ret isa map then ret[@i] = @self[@i]
  • end for
  • return ret
  • end function
  • map.filter = @list.filter
  • list.filterKv = function(func, inst = null)
  • ret = null
  • if self isa list then ret = []
  • if self isa map then ret = {}
  • for i in self.indexes
  • arg = {"key": @i, "value": @self[@i]}
  • if not funcRef.invoke(@func, arg, @inst) then continue
  • if ret isa list then ret.push(self[@i])
  • if ret isa map then ret[@i] = @self[@i]
  • end for
  • return ret
  • end function
  • map.filterKv = @list.filterKv
  • list.forEach = function(func, inst = null)
  • for i in self
  • funcRef.invoke @func, @i, @inst
  • end for
  • return self
  • end function
  • map.forEach = @list.forEach
  • list.forEachKv = function(func, inst = null)
  • for i in self.indexes
  • funcRef.invoke @func, {"key": @i, "value": @self[@i]}, @inst
  • end for
  • return self
  • end function
  • map.forEachKv = @list.forEachKv
  • list.findOrElse = function(self, func, default = null, inst = null)
  • for val in self.values
  • if @func isa funcRef and funcRef.invoke(@func, @val, @inst) then return @val
  • if not @func isa funcRef and @val == func then return @val
  • end for
  • return @default
  • end function
  • map.findOrElse = @list.findOrElse
  • list.find = @list.findOrElse
  • map.find = @list.find
  • list.findIsa = function(type, default = null)
  • for val in self.values
  • if val isa @type then return val
  • end for
  • return default
  • end function
  • list.getOrElse = function(key, default)
  • if not self.hasIndex(@key) then return @default
  • return self[@key]
  • end function
  • map.getOrElse = @list.getOrElse
  • list.ifEmptyThen = function(default)
  • if self.len == 0 then return default
  • return self
  • end function
  • map.ifEmptyThen = @list.ifEmptyThen
  • list.map = function(func, inst = null)
  • ret = null
  • if self isa list then ret = []
  • if self isa map then ret = {}
  • for i in self.indexes
  • if self isa list then ret.push funcRef.invoke(@func, @self[i], inst)
  • if self isa map then ret[@i] = funcRef.invoke(@func, @self[@i], inst)
  • end for
  • return ret
  • end function
  • map.map = @list.map
  • list.mapUnless = function(func, abortType)
  • ret = null
  • if self isa list then ret = []
  • if self isa map then ret = {}
  • for i in self.indexes
  • e = func(@self[@i])
  • if e isa abortType then return @e
  • if self isa list then ret.push @e
  • if self isa map then ret[@i] = @e
  • end for
  • return ret
  • end function
  • map.mapUnless = @list.mapUnless
  • list.tryGet = function(key)
  • return self.getOrElse(@key, null)
  • end function
  • map.tryGet = @list.tryGet
  • list.tryPush = function(value)
  • if @value then self.push(@value)
  • return self
  • end function
  • map.tryPush = @list.tryPush
  • list.trySeek = function(keys, default = null)
  • ptr = self
  • for key in keys
  • if not ptr.hasIndex(@key) then return default
  • ptr = ptr[@key]
  • end for
  • return ptr
  • end function
  • map.trySeek = @list.trySeek
  • list.unique = function()
  • i = 0
  • k = self.len - 2
  • while i <= k
  • obj = self[i]
  • for j in range(self.len - 1, i + 1)
  • if self[i] == self[j] then self.remove(j)
  • end for
  • i = i + 1
  • k = self.len - 2
  • end while
  • return self
  • end function
  • map.addRange = function(a, b)
  • for i in a.indexes
  • self[a[i]] = b[i]
  • end for
  • return self
  • end function
  • map.addInverse = function()
  • for kv in self
  • self[@kv.value] = @kv.key
  • end for
  • return self
  • end function
  • funcRef.curry = function(inst, toCurry, reverse = false)
  • ret = function(obj)
  • if reverse then return toCurry(@obj, @outer.inst)
  • return toCurry(@outer.inst, @obj)
  • end function
  • return @ret
  • end function
  • funcRef.invoke = function(func, arg, inst = null)
  • if @inst then return func(@inst, @arg)
  • return func(@arg)
  • end function
  • globals.UTIL_DEFINED = true
  • end if