From 5c8d97d8d4458f74d38968d51e116001306af356 Mon Sep 17 00:00:00 2001 From: Mike Nolan Date: Mon, 30 Dec 2024 05:56:46 -0600 Subject: [PATCH] First commit --- .gitignore | 3 + LICENSE.md | 157 ++++ README.md | 15 + Tesses.CrossLang.BuildEssentials/cross.json | 11 + Tesses.CrossLang.BuildEssentials/main.tcross | 11 + .../src/PackageManager.tcross | 136 +++ .../src/buildtool.tcross | 227 +++++ .../src/crossvmfile.tcross | 149 ++++ .../src/version.tcross | 103 +++ Tesses.CrossLang.Markup/cross.json | 11 + Tesses.CrossLang.Markup/src/markup.tcross | 818 ++++++++++++++++++ Tesses.CrossLang.PackageServer/cross.json | 10 + .../pages/index.tcrml | 3 + .../src/program.tcross | 4 + Tesses.CrossLang.Shell/cross.json | 14 + Tesses.CrossLang.Shell/src/main.tcross | 4 + install.sh | 1 + newtonsoft_json_config_schema.cs | 48 + project_types.txt | 6 + script.sh | 3 + 20 files changed, 1734 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 Tesses.CrossLang.BuildEssentials/cross.json create mode 100644 Tesses.CrossLang.BuildEssentials/main.tcross create mode 100644 Tesses.CrossLang.BuildEssentials/src/PackageManager.tcross create mode 100644 Tesses.CrossLang.BuildEssentials/src/buildtool.tcross create mode 100644 Tesses.CrossLang.BuildEssentials/src/crossvmfile.tcross create mode 100644 Tesses.CrossLang.BuildEssentials/src/version.tcross create mode 100644 Tesses.CrossLang.Markup/cross.json create mode 100644 Tesses.CrossLang.Markup/src/markup.tcross create mode 100644 Tesses.CrossLang.PackageServer/cross.json create mode 100644 Tesses.CrossLang.PackageServer/pages/index.tcrml create mode 100644 Tesses.CrossLang.PackageServer/src/program.tcross create mode 100644 Tesses.CrossLang.Shell/cross.json create mode 100644 Tesses.CrossLang.Shell/src/main.tcross create mode 100755 install.sh create mode 100644 newtonsoft_json_config_schema.cs create mode 100644 project_types.txt create mode 100755 script.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2591e1f --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +bin +bin-tmp +obj \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..144f824 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,157 @@ +# GNU LESSER GENERAL PUBLIC LICENSE + +Version 3, 29 June 2007 + +Copyright (C) 2007 Free Software Foundation, Inc. + + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + +This version of the GNU Lesser General Public License incorporates the +terms and conditions of version 3 of the GNU General Public License, +supplemented by the additional permissions listed below. + +## 0. Additional Definitions. + +As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the +GNU General Public License. + +"The Library" refers to a covered work governed by this License, other +than an Application or a Combined Work as defined below. + +An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + +A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + +The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + +The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + +## 1. Exception to Section 3 of the GNU GPL. + +You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + +## 2. Conveying Modified Versions. + +If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + +- a) under this License, provided that you make a good faith effort + to ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or +- b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + +## 3. Object Code Incorporating Material from Library Header Files. + +The object code form of an Application may incorporate material from a +header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + +- a) Give prominent notice with each copy of the object code that + the Library is used in it and that the Library and its use are + covered by this License. +- b) Accompany the object code with a copy of the GNU GPL and this + license document. + +## 4. Combined Works. + +You may convey a Combined Work under terms of your choice that, taken +together, effectively do not restrict modification of the portions of +the Library contained in the Combined Work and reverse engineering for +debugging such modifications, if you also do each of the following: + +- a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. +- b) Accompany the Combined Work with a copy of the GNU GPL and this + license document. +- c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. +- d) Do one of the following: + - 0) Convey the Minimal Corresponding Source under the terms of + this License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + - 1) Use a suitable shared library mechanism for linking with + the Library. A suitable mechanism is one that (a) uses at run + time a copy of the Library already present on the user's + computer system, and (b) will operate properly with a modified + version of the Library that is interface-compatible with the + Linked Version. +- e) Provide Installation Information, but only if you would + otherwise be required to provide such information under section 6 + of the GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the Application + with a modified version of the Linked Version. (If you use option + 4d0, the Installation Information must accompany the Minimal + Corresponding Source and Corresponding Application Code. If you + use option 4d1, you must provide the Installation Information in + the manner specified by section 6 of the GNU GPL for conveying + Corresponding Source.) + +## 5. Combined Libraries. + +You may place library facilities that are a work based on the Library +side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + +- a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities, conveyed under the terms of this License. +- b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + +## 6. Revised Versions of the GNU Lesser General Public License. + +The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +as you received it specifies that a certain numbered version of the +GNU Lesser General Public License "or any later version" applies to +it, you have the option of following the terms and conditions either +of that published version or of any later version published by the +Free Software Foundation. If the Library as you received it does not +specify a version number of the GNU Lesser General Public License, you +may choose any version of the GNU Lesser General Public License ever +published by the Free Software Foundation. + +If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..23630ca --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# CrossLang Essentials + +> :warning: **NOT READY FOR PRODUCTION** + +[CrossLang](https://gitea.site.tesses.net/tesses50/crosslang) is required to build this + +# To Build +```bash +./script.sh +``` + +# To Install +```bash +./install.sh +``` \ No newline at end of file diff --git a/Tesses.CrossLang.BuildEssentials/cross.json b/Tesses.CrossLang.BuildEssentials/cross.json new file mode 100644 index 0000000..03e636d --- /dev/null +++ b/Tesses.CrossLang.BuildEssentials/cross.json @@ -0,0 +1,11 @@ +{ + "name": "Tesses.CrossLang.BuildEssentials", + "version": "1.0.0.0-prod", + "info": { + "maintainer": "Mike Nolan", + "type": "lib", + "repo": "https://gitea.site.tesses.net/tesses50/crosslang/crosslang-libs", + "homepage": "https://crosslang.tesseslanguage.com/", + "license": "LGPLv3" + } +} \ No newline at end of file diff --git a/Tesses.CrossLang.BuildEssentials/main.tcross b/Tesses.CrossLang.BuildEssentials/main.tcross new file mode 100644 index 0000000..c26ac48 --- /dev/null +++ b/Tesses.CrossLang.BuildEssentials/main.tcross @@ -0,0 +1,11 @@ +func main(args) +{ + var pm = Tesses.CrossLang.PackageManager(); + //pm.Offline=true; + //Console.WriteLine(pm.GetLatest("MyPackage")); + //Console.WriteLine(Json.Encode(pm.ParseFileName("BeautifulApp-John-1.0.0.0-prod.crvm"))); + + var tool = Tesses.CrossLang.BuildTool(pm); + tool.BuildProject(args[1]); + +} \ No newline at end of file diff --git a/Tesses.CrossLang.BuildEssentials/src/PackageManager.tcross b/Tesses.CrossLang.BuildEssentials/src/PackageManager.tcross new file mode 100644 index 0000000..db6a725 --- /dev/null +++ b/Tesses.CrossLang.BuildEssentials/src/PackageManager.tcross @@ -0,0 +1,136 @@ +func Tesses.CrossLang.PackageManager() +{ + func ParseFileName(name) + { + + var index = name.LastIndexOf('.'); + if(index == -1) throw "We expect an extension"; + if(name.Substring(index) != ".crvm") throw "We expect the extension .crvm"; + name = name.Substring(0,index); + //Name-VERSION-[dev|alpha|beta|prod] + + var lastIndex = name.LastIndexOf('-'); + var verStage = name.Substring(lastIndex+1); + var versionStr = verStage; + if(verStage == "dev" || verStage == "alpha" || verStage == "beta" || verStage == "prod") + { + var lastIndex2 = name.LastIndexOf('-', lastIndex-1); + return { + Name = name.Substring(0,lastIndex2), + Version = name.Substring(lastIndex2+1) + }; + } + else + { + return { + Name = name.Substring(0,lastIndex), + Version = name.Substring(lastIndex+1) + }; + } + } + var configRoot = Path.FromString(Env.Config) / "Tesses" / "CrossLang"; + var packageCache = configRoot / "PackageCache"; + FS.Local.CreateDirectory(packageCache); + func FileReadByteArray(fs,path) + { + var f = fs.OpenFile(path,"rb"); + var ms = FS.MemoryStream(true); + f.CopyTo(ms); + var buff = ms.GetBytes(); + f.Close(); + return buff; + } + func FileReadString (fs,path) { + var buff = FileReadByteArray(fs,path).ToString(); + ms.Close(); + return text; + } + return { + Offline = false, + ParseFileName, + GetPackageServers = ()=>{ + var packageConfigFile = configRoot / "package_servers.json"; + if(FS.Local.RegularFileExists(packageConfigFile)) + { + return Json.Decode(FileReadString(FS.Local, packageConfigFile)); + } + return ["https://cpkg.tesseslanguage.com/"]; + }, + GetPackage = (this,name, version) => + { + var v = Tesses.CrossLang.Version.Parse(version); + var useCache = v.Stage != Tesses.CrossLang.Version.Dev; + var pkgFile = packageCache / name / v.ToString(); + if(useCache && FS.Local.RegularFileExists(pkgFile)) + { + return FileReadByteArray(FS.Local,pkgFile); + } + if(this.Offline) return null; + + each(var item : this.GetPackageServers()) + { + //https://cpkg.tesseslanguage.com/api/v1/download?name=MyPackage&version=1.0.0.0-prod + var uri = $"{item.TrimEnd('/')}/api/v1/download?name={Net.Http.UrlEncode(name)}&version={Net.Http.UrlEncode(version)}"; + var req = Net.Http.MakeRequest(uri); + if(req.StatusCode == 200) + { + var strm = FS.MemoryStream(true); + req.CopyToStream(strm); + + if(useCache) { + FS.Local.CreateDirectory(packageCache / name); + var f = FS.Local.OpenFile(pkgFile,"wb"); + strm.Seek(0,0); + strm.CopyTo(f); + f.Close(); + } + var data = strm.GetBytes(); + strm.Close(); + req.Close(); + return data; + } + } + return null; + }, + GetLatest = (this,name) => { + var pkgServers = this.GetPackageServers(); + if(this.Offline || pkgServers.Count == 0) + { + //user has declared they are offline or don't have packageServers look through packages locally + var version = Tesses.CrossLang.Version.Create(0,0,0,0,0); + var configRoot = Path.FromString(Env.Config) / "Tesses" / "CrossLang"; + var dir = configRoot / "PackageCache" / name; + if(FS.Local.DirectoryExists(dir)) + each(var f : FS.Local.EnumeratePaths(dir)) + { + var v = Tesses.CrossLang.Version.Parse(f.GetFileName()); + if(v >= version) + { + version = v; + } + } + + if(version.VersionInt == 0) return null; + return version.ToString(); + } + else + { + each(var item : pkgServers) + { + var uri = $"{item.TrimEnd('/')}/api/v1/latest?name={Net.Http.UrlEncode(name)}"; + var req = Net.Http.MakeRequest(uri); + if(req.StatusCode == 200) + { + var res0 = req.ReadAsString(); + + var res = Json.Decode(res0); + req.Close(); + return res.version; + } + } + + } + return null; + } + }; +} \ No newline at end of file diff --git a/Tesses.CrossLang.BuildEssentials/src/buildtool.tcross b/Tesses.CrossLang.BuildEssentials/src/buildtool.tcross new file mode 100644 index 0000000..2b2f8d1 --- /dev/null +++ b/Tesses.CrossLang.BuildEssentials/src/buildtool.tcross @@ -0,0 +1,227 @@ +func Tesses.CrossLang.BuildTool(pm) +{ + func copyFile(src,dest) + { + var src = FS.Local.OpenFile(src,"rb"); + var dest = FS.Local.OpenFile(dest, "wb"); + src.CopyTo(dest); + src.Close(); + dest.Close(); + } + + return { + DirectoriesCompiled = [], + FileReadString = (fs,path) =>{ + var f = fs.OpenFile(path,"rb"); + var ms = FS.MemoryStream(true); + f.CopyTo(ms); + var text = ms.GetBytes().ToString(); + f.Close(); + ms.Close(); + return text; + }, + GetPackageDependencies = (this,name,version,dir)=>{ + var dep = pm.GetPackage(name,version); + if(TypeOf(dep) == "Null") throw $"Package {name} with version {version} does not exist"; + var pkgPath = dir / $"{name}-{version}.crvm"; + var strm = FS.Local.OpenFile(pkgPath,"wb"); + strm.WriteBlock(dep,0,dep.Count); + strm.Close(); + var ms = MemoryStream(true); + ms.WriteBlock(dep,0,dep.Count); + ms.Seek(0,0); + var package = Tesses.CrossLang.CrossVMFile(); + package.Load(ms); + ms.Close(); + + var deps = []; + + each(var dep : package.Dependencies) + { + deps.Add(this.GetPackageDependencies(dep.Name, dep.Version, dir)); + } + + + return { + Name = name, + Version = version, + Info = package.Info, + Dependencies = deps, + Output = pkgPath + }; + }, + BuildProject = (this,projectDirectory)=>{ + + var dir = FS.MakeFull(projectDirectory); + var dirStr = dir.ToString(); + + each(var item : this.DirectoriesCompiled) + { + if(item.Path == dirStr) return item.Data; + } + + var crossConf = dir / "cross.json"; + if(FS.Local.FileExists(crossConf)) + { + var configData = Json.Decode(this.FileReadString(FS.Local,crossConf)); + var info = {type = "console"}; + var name = "out"; + var version = "1.0.0.0-prod"; + var outputDir = "bin"; + var objDir = "obj"; + var srcDir = "src"; + var resDir = "res"; + if(TypeOf(configData.name) != "Undefined") + name = configData.name; + + if(TypeOf(configData.version) != "Undefined") + version = configData.version; + if(TypeOf(configData.bin_directory) != "Undefined") + outputDir = configData.bin_directory; + + if(TypeOf(configData.obj_directory) != "Undefined") + outputDir = configData.obj_directory; + if(TypeOf(configData.source_directory) != "Undefined") + srcDir = configData.source_directory; + if(TypeOf(configData.resource_directory) != "Undefined") + resDir = configData.resource_directory; + if(TypeOf(configData.info) != "Undefined") + info = configData.info; + + FS.Local.CreateDirectory(dir / outputDir); + + FS.Local.CreateDirectory(dir / objDir / "packages"); + + FS.Local.CreateDirectory(dir/resDir); + + var dependencies = []; + if(TypeOf(configData.project_dependencies) == "List") + { + each(var dep : configData.project_dependencies) + { + dependencies.Add(this.BuildProject(dep)); + } + } + var sources = []; + if(TypeOf(configData.dependencies) == "List") + { + each(var dep : configData.project_dependencies) + { + dependencies.Add(this.GetPackageDependencies(dep.Name,dep.Version,dir / objDir / "packages")); + } + } + + each(var item : this.DirectoriesCompiled) + { + if(item.Path == dirStr) return item.Data; + } + + + func walk_for_compiling(item,dir2) + { + if(item.Info.type == "compile_tool") + { + var newDir = dir / objDir / $"{item.Name}-{item.Version}"; + FS.Local.CreateDirectory(newDir); + var newFile = newDir / $"{item.Name}-{item.Version}.crvm"; + + copyFile(item.Output, newFile); + each(var item2 : item.Dependencies) + { + walk_for_compiling(item2, newDir); + } + //we need to load this + var env = VM.CreateEnvironment({}); + env.RegisterEverything(); + env.LockRegister(); + + env.LoadFileWithDependencies(FS.Local,newFile); + env.GetDictionary().RunTool({ + Project = FS.SubdirFilesystem(FS.Local, dir), + ProjectInfo = info, + GeneratedSource = sources + }); + } + else + { + copyFile(item.Output, dir2 / $"{item.Name}-{item.Version}.crvm"); + each(var item2 : item.Dependencies) + { + walk_for_compiling(item2, dir2); + } + } + } + + var file_deps = []; + + each(var dep : dependencies) + { + if(dep.Info.type == "lib") + { + file_deps.Add({ + Name = dep.Name, + Version = dep.Version + }); + } + walk_for_compiling(dep,dir / outputDir); + } + + func walk_for_source(sourceDir) + { + each(var file : FS.Local.EnumeratePaths(sourceDir)) + { + if(FS.Local.RegularFileExists(file)) + { + var src = { + FileName = file.ToString(), + Source = this.FileReadString(FS.Local, file) + }; + sources.Add(src); + } + else if(FS.Local.DirectoryExists(file)) + { + walk_for_source(file); + } + } + } + + walk_for_source(dir / srcDir); + + + var output = $"{name}-{version}.crvm"; + var outFile = FS.Local.OpenFile(dir / outputDir / output,"wb"); + + var result = VM.Compile({ + Name = name, + Version = version, + Sources = sources, + Info = Json.Encode(info), + ResourceFileSystem = FS.SubdirFilesystem(FS.Local, dir / resDir), + Dependencies = file_deps, + Output = outFile + }); + + outFile.Close(); + if(!result.Success) + { + throw result.Reason; + } + + var myData = { + Name = name, + Version = version, + Info = info, + Output = dir / outputDir / output, + Dependencies = dependencies + }; + this.DirectoriesCompiled.Add({ + Path = dirStr, + Data = myData + }); + + return myData; + } + return null; + } + }; +} \ No newline at end of file diff --git a/Tesses.CrossLang.BuildEssentials/src/crossvmfile.tcross b/Tesses.CrossLang.BuildEssentials/src/crossvmfile.tcross new file mode 100644 index 0000000..0730407 --- /dev/null +++ b/Tesses.CrossLang.BuildEssentials/src/crossvmfile.tcross @@ -0,0 +1,149 @@ +func Tesses.CrossLang.CrossVMFile() +{ + return { + Info = "", + Name = "", + Version = "", + Dependencies = [], + Chunks = [], + Strings = [], + Functions = [], + Resources = [], + Sections = [], + Ensure = (this,strm,buff,len) =>{ + if(strm.ReadBlock(buff,0,len) != len) + throw $"Could not read {len} byte(s)"; + }, + EnsureInt = (this,strm)=>{ + var buff = ByteArray(4); + this.Ensure(strm,buff,4); + var number = 0; + number |= buff[0] << 24; + number |= buff[1] << 16; + number |= buff[2] << 8; + number |= buff[3]; + return number; + }, + EnsureString = (this,strm)=>{ + var len = this.EnsureInt(strm); + var buff = ByteArray(len); + this.Ensure(strm, buff,len); + return buff.ToString(); + }, + GetString = (this,strm)=>{ + var index = this.EnsureInt(strm); + if(index < this.Strings.Count) return this.Strings[index]; + throw $"{index} is not less than {this.Strings.Count}"; + }, + Read = (this,stream)=>{ + var header = ByteArray(8); + this.Ensure(stream, header, header.Count); + + var hdrStr = header.ToString(); + if(hdrStr != "TCROSSVM") throw "Invalid TCrossVM image."; + + this.Ensure(stream, header, 5); + + var version = Tesses.CrossLang.Version.FromBytes(header, 0); + + if(version > Tesses.CrossLang.Version.Current) throw "Runtime is too old."; + this.Ensure(stream, header, 5); + + + this.Version = Tesses.CrossLang.Version.FromBytes(header,0); + + var sec = ByteArray(4); + var sectionCount = this.EnsureInt(stream); + + + for(var i = 0; i < sectionCount; i++) + { + + this.Ensure(stream, sec, sec.Count); + hdrStr = sec.ToString(); + var tableLength = this.EnsureInt(stream); + if(hdrStr == "NAME") + { + this.Name = this.GetString(stream); + } + else if(hdrStr == "INFO") + { + this.Info = this.GetString(stream); + } + else if(hdrStr == "DEPS") + { + var _name = this.GetString(stream); + this.Ensure(stream, header, 5); + var _version = Tesses.CrossLang.Version.FromBytes(header,0); + this.Dependencies.Add({ + Name = _name, + Version = _version + }); + } + else if(hdrStr == "RESO") + { + var resource = ByteArray(tableLength); + this.Ensure(stream,resource,resource.Count); + this.Resources.Add(resource); + } + else if(hdrStr == "CHKS") + { + var chunkCount = this.EnsureInt(stream); + for(var j = 0; j < chunkCount; j++) + { + var _args = []; + var _argCount = this.EnsureInt(stream); + for(var k = 0; k < _argCount; k++) + { + _args.Add(this.GetString(stream)); + } + var _code = ByteArray(this.EnsureInt(stream)); + this.Ensure(stream,_code,_code.Count); + var chunk = { + Arguments = _args, + Code = _code + }; + this.Chunks.Add(chunk); + } + } + else if(hdrStr == "FUNS") + { + var funLen = this.EnsureInt(stream); + for(var j = 0; j < funLen; j++) + { + var fnPartsCount = this.EnsureInt(stream); + var documentation = ""; + var fnParts = []; + for(var k = 0; k < fnPartsCount; k++) + { + if(k == 0) documentation = this.GetString(stream); + else fnParts.Add(this.GetString(stream)); + } + var fnId = this.EnsureInt(stream); + this.Functions.Add({ + Documentation=documentation, + FunctionNameParts = fnParts, + Closure = fnId + }); + } + } + else if(hdrStr == "STRS") + { + var strcnt = this.EnsureInt(stream); + for(var j = 0; j < strcnt; j++) + { + this.Strings.Add(this.EnsureString(stream)); + } + } + else { + var data = ByteArray(tableLength); + this.Ensure(stream,data,data.Count); + this.Sections.Add({ + Name=hdrStr, + Data = data + }); + } + } + } + }; +} \ No newline at end of file diff --git a/Tesses.CrossLang.BuildEssentials/src/version.tcross b/Tesses.CrossLang.BuildEssentials/src/version.tcross new file mode 100644 index 0000000..d243398 --- /dev/null +++ b/Tesses.CrossLang.BuildEssentials/src/version.tcross @@ -0,0 +1,103 @@ +func Tesses.CrossLang.Version.Create(major,minor,patch,build,stage) +{ + return { + Major = major, + Minor = minor, + Patch = patch, + Build = build, + Stage = stage, + getBuildAsInt = (this)=>{ + return ((this.Build & 0x3FFF) << 2) | ((this.Stage & 0x03)); + }, + getVersionInt = (this)=>{ + return ((this.Major & 0xFF) << 32) | ((this.Minor & 0xFF) << 24) + | ((this.Patch & 0xFF) << 16) | (this.BuildAsInt & 0xFFFF); + }, + operator< = (this,right)=>{ + return this.VersionInt < right.VersionInt; + }, + operator> = (this,right)=>{ + return this.VersionInt > right.VersionInt; + }, + operator== = (this,right)=>{ + return this.VersionInt == right.VersionInt; + }, + operator<= = (this,right)=>{ + return this.VersionInt <= right.VersionInt; + }, + operator>= = (this,right)=>{ + return this.VersionInt >= right.VersionInt; + }, + operator!= = (this,right)=>{ + return this.VersionInt != right.VersionInt; + }, + ToString = (this) => { + var stage = this.Stage == 0 ? "dev" : this.Stage == 1 ? "alpha" : this.Stage == 2 ? "beta" : "prod"; + return $"{this.Major & 0xFF}.{this.Minor & 0xFF}.{this.Patch & 0xFF}.{this.Build & 0x3FFF}-{stage}"; + }, + ToBytes = (this, buff, off) => { + if((buff.Count - offset) < 5) throw "Not long enough"; + buff[off] = this.Major; + buff[off+1] = this.Minor; + buff[off+2] = this.Patch; + var b = this.BuildAsInt; + buff[off+3] = (b >> 8) & 0xFF; + buff[off+4] = b & 0xFF; + } + }; +} +func Tesses.CrossLang.Version.FromBytes(buffer, offset) +{ + + if((buffer.Count - offset) < 5) throw "Not long enough"; + + var major = buffer[offset]; + var minor = buffer[offset+1]; + var patch = buffer[offset+2]; + + var buildI = (buffer[offset+3] << 8) | (buffer[offset+4]); + + var build = (buildI >> 2); + + + var stage = buildI & 0x03; + + var b = Tesses.CrossLang.Version.Create(major,minor,patch,build,stage); + return b; +} +func Tesses.CrossLang.Version.CreateEmpty() +{ + return Tesses.CrossLang.Version.Create(1,0,0,0,Tesses.CrossLang.Version.Prod); +} +func Tesses.CrossLang.Version.Parse(ver) +{ + var mySplit = ver.Split("-",false,2); + var version = 3; + if(mySplit.Count >= 1) + { + if(mySplit.Count == 2) + { + if(mySplit[1] == "dev") version = 0; + else if(mySplit[1] == "alpha") version = 1; + else if(mySplit[2] == "beta") version = 2; + } + var vpart = mySplit[0].Split(".",false,4); + var major = 1; + var minor = 0; + var patch = 0; + var build = 0; + + if(vpart.Count >= 1) major = ParseLong(vpart[0]); if(TypeOf(major) != "Long") major = 1; + if(vpart.Count >= 2) minor = ParseLong(vpart[1]); if(TypeOf(minor) != "Long") minor = 0; + if(vpart.Count >= 3) patch = ParseLong(vpart[2]); if(TypeOf(patch) != "Long") patch = 0; + if(vpart.Count >= 4) build = ParseLong(vpart[3]); if(TypeOf(build) != "Long") build = 0; + + return Tesses.CrossLang.Version.Create(major,minor,patch,build,version); + } +} +Tesses.CrossLang.Version.Dev = 0; +Tesses.CrossLang.Version.Alpha = 1; +Tesses.CrossLang.Version.Beta = 2; +Tesses.CrossLang.Version.Prod = 3; + +Tesses.CrossLang.Version.Current = Tesses.CrossLang.Version.Create(1,0,0,0,Tesses.CrossLang.Version.Prod); \ No newline at end of file diff --git a/Tesses.CrossLang.Markup/cross.json b/Tesses.CrossLang.Markup/cross.json new file mode 100644 index 0000000..59978b3 --- /dev/null +++ b/Tesses.CrossLang.Markup/cross.json @@ -0,0 +1,11 @@ +{ + "name": "Tesses.CrossLang.Markup", + "version": "1.0.0.0-prod", + "info": { + "maintainer": "Mike Nolan", + "type": "compile_tool", + "repo": "https://gitea.site.tesses.net/tesses50/crosslang/crosslang-libs", + "homepage": "https://crosslang.tesseslanguage.com/", + "license": "LGPLv3" + } +} \ No newline at end of file diff --git a/Tesses.CrossLang.Markup/src/markup.tcross b/Tesses.CrossLang.Markup/src/markup.tcross new file mode 100644 index 0000000..48316a4 --- /dev/null +++ b/Tesses.CrossLang.Markup/src/markup.tcross @@ -0,0 +1,818 @@ +func crossmarkuplexer(data) +{ + var tokens = []; + var i = 0; + var peeked=null; + var inSpecial=false; + + var builder = ""; + func read() + { + if(peeked) + { + var myPeeked=peeked; + peeked = null; + return myPeeked; + } + if(i < data.Length) { + var rc = data[i++]; + return rc; + } + + return null; + } + + func peek() + { + if(peeked) return peeked; + peeked = read(); + return peeked; + } + + + + func flush() + { + if(builder.Count > 0) + { + tokens.Add({ + Type = inSpecial ? "Identifier" : "Text", + Text = builder + }); + builder = ""; + } + } + + func ReadChar() + { + var r2 = read(); + + if(!r2) return null; + if(r2 == '\\') + { + r2 = read(); + if(!r2) + { + return null; + } + + return $"\\{r2}"; + } + + return r2.ToString(); + } + + func ReadString() + { + var str = ""; + while(var myChar = ReadChar()) + { + if(myChar == "\"") break; + str += myChar; + } + return str; + } + + while(r = read()) + { + var p = peek(); + if(!inSpecial && r == '<') + { + if(p == '?') + { + read(); + + + flush(); + + tokens.Add({ + Type = "EnterSpecial" + }); + + + inSpecial=true; + + } + else + { + builder += "<"; + } + } + else if(inSpecial && (r == '\r' || r == '\n' || r == ' ' || r == '\t')) + { + flush(); + } + else if(inSpecial && r == '\"') + { + flush(); + var myStr = ReadString(); + tokens.Add({ + Type = "String", + Text = myStr + }); + } + else if(inSpecial && r == '\'') + { + flush(); + var myChr = ReadChar(); + tokens.Add({ + Type = "Char", + Text = myChr + }); + read(); + } + else if(inSpecial && r == '=') + { + flush(); + tokens.Add({ + Type = "Equals" + }); + } + else if(inSpecial && r == '(') + { + flush(); + tokens.Add({ + Type = "OpenParen" + }); + } + else if(inSpecial && r == ')') + { + flush(); + tokens.Add({ + Type = "CloseParen" + }); + } + else if(inSpecial && r == ',') + { + flush(); + tokens.Add({ + Type = "Comma" + }); + } + else if(inSpecial && r == '?') + { + if(p == '?') + { + read(); + builder += "?"; + } + else if(p == '>') + { + read(); + + flush(); + tokens.Add({ + Type = "ExitSpecial" + }); + inSpecial=false; + } + else + { + builder += read().ToString(); + } + } + else + { + builder += r.ToString(); + } + } + + flush(); + + return tokens; +} + +func crossmarkupparser(tokens) +{ + var i = 0; + + func NotEnd() + { + if(i + 3 > tokens.Count) return false; + + if(tokens[i].Type != "EnterSpecial") + return true; + + if(tokens[i+1].Type != "Identifier") + return true; + if(tokens[i+1].Text != "end") + return true; + if(tokens[i+2].Type != "ExitSpecial") + return true; + + return false; + } + + func EnsureEnd() + { + if(NotEnd()) + { + throw "Must end with "; + } + i += 3; + } + + func TokenTypeIs(type) + { + return i < tokens.Length && tokens[i].Type == type; + } + + func EnsureTokenType(type) + { + if(!TokenTypeIs(type)) + { + throw $"The token is {type} which is not {tokens[i].Type}"; + } + i++; + } + + func ConsumeIfTokenTypeIs(type) + { + if(TokenTypeIs(type)) i++; + } + + func parse_node() + { + if(i < tokens.Length) + { + var myToken = tokens[i++]; + if(myToken.Type == "EnterSpecial") + { + if(i < tokens.Length) + { + var myToken2 = tokens[i++]; + if(myToken2.Type == "Identifier") + { + if(myToken2.Text == "page") + { + var pageargs = []; + var nodes =[]; + var route = "/"; + var router_function = "Router"; + //its a page + + EnsureTokenType("OpenParen"); + while(!TokenTypeIs("CloseParen")) + { + + ConsumeIfTokenTypeIs("Comma"); + if(i < tokens.Length && tokens[i].Type == "Identifier") + { + pageargs.Add(tokens[i].Text); + i++; + } + } + EnsureTokenType("CloseParen"); + + while(!TokenTypeIs("ExitSpecial")) + { + if(TokenTypeIs("Identifier")) + { + var key = tokens[i++].Text; + EnsureTokenType("Equals"); + if(TokenTypeIs("String")) + { + var value = tokens[i++].Text; + if(key == "route") + route = value; + else if(key == "router_function") + router_function = value; + else + throw $"Unknown property {key}"; + } + else + { + throw "Not a string"; + } + } + else + { + throw "Not an identifier"; + } + } + + EnsureTokenType("ExitSpecial"); + while(NotEnd()) + { + nodes.Add(parse_node()); + } + EnsureEnd(); + + + return { + + Type = "PageNode", + Arguments = pageargs, + Route = route, + RouterFunction = router_function, + Nodes = nodes + }; + } + else if(myToken2.Text == "component") + { + var pageargs = []; + var nodes =[]; + var name = "Component"; + //its a component + + EnsureTokenType("OpenParen"); + while(!TokenTypeIs("CloseParen")) + { + + ConsumeIfTokenTypeIs("Comma"); + if(i < tokens.Length && tokens[i].Type == "Identifier") + { + pageargs.Add(tokens[i].Text); + i++; + } + } + EnsureTokenType("CloseParen"); + + while(!TokenTypeIs("ExitSpecial")) + { + if(TokenTypeIs("Identifier")) + { + var key = tokens[i++].Text; + EnsureTokenType("Equals"); + if(TokenTypeIs("String")) + { + var value = tokens[i++].Text; + if(key == "name") + name = value; + else + throw $"Unknown property {key}"; + } + else + { + throw "Not a string"; + } + } + else + { + throw "Not an identifier"; + } + } + + EnsureTokenType("ExitSpecial"); + while(NotEnd()) + { + nodes.Add(parse_node()); + } + EnsureEnd(); + + + return { + + Type = "ComponentNode", + Arguments = pageargs, + Name = name, + Nodes = nodes + }; + } + else if(myToken2.Text == "code") + { + var nodes = []; + while(!TokenTypeIs("ExitSpecial")) + { + if(i < tokens.Length) + nodes.Add(parse_node()); + } + EnsureTokenType("ExitSpecial"); + return { + Type = "CodeNode", + Nodes = nodes + }; + } + else if(myToken2.Text == "resource") + { + var name = ""; + var route = ""; + var router_function = "Router"; + while(!TokenTypeIs("ExitSpecial")) + { + if(TokenTypeIs("Identifier")) + { + var key = tokens[i++].Text; + EnsureTokenType("Equals"); + if(TokenTypeIs("String")) + { + var value = tokens[i++].Text; + if(key == "name") + name = value; + else if(key == "route") + route = value; + else if(key == "router_function") + router_function = value; + else + throw $"Unknown property {key}"; + } + else + { + throw "Not a string"; + } + } + else + { + throw "Not an identifier"; + } + } + EnsureTokenType("ExitSpecial"); + return { + Type = "EmbedNode", + Name = name, + Route = route, + RouterFunction = router_function + }; + } + else if(myToken2.Text == "expr") + { + var nodes = []; + while(!TokenTypeIs("ExitSpecial")) + { + if(i < tokens.Length) + nodes.Add(parse_node()); + } + + EnsureTokenType("ExitSpecial"); + return { + Type = "ExprNode", + Nodes = nodes + }; + } + else + { + EnsureTokenType("ExitSpecial"); + + var args = []; + + while(NotEnd()) + { + if(TokenTypeIs("Text")) + { + EnsureTokenType("Text"); + } + else if(TokenTypeIs("EnterSpecial")) + { + EnsureTokenType("EnterSpecial"); + + var myToken3 = tokens[i++]; + + if(myToken3.Type == "Identifier") + { + if(myToken3.Text == "arg") + { + var nodes = []; + while(!TokenTypeIs("ExitSpecial")) + { + if(i < tokens.Length) + nodes.Add(parse_node()); + } + EnsureTokenType("ExitSpecial"); + + args.Add({ + Type = "ArgNode", + Nodes = nodes + }); + } + else if(myToken3.Text == "arg_component") + { + var pageargs = []; + var nodes =[]; + //its a component + + EnsureTokenType("OpenParen"); + while(!TokenTypeIs("CloseParen")) + { + + ConsumeIfTokenTypeIs("Comma"); + if(i < tokens.Length && tokens[i].Type == "Identifier") + { + pageargs.Add(tokens[i].Text); + i++; + } + } + EnsureTokenType("CloseParen"); + EnsureTokenType("ExitSpecial"); + while(NotEnd()) + { + nodes.Add(parse_node()); + } + EnsureEnd(); + + args.Add({ + Type = "ArgComponentNode", + Arguments = pageargs, + Nodes = nodes + }); + } + } + else + { + throw "Must be an identifier"; + } + } + } + EnsureEnd(); + return { + Type = "UseComponentNode", + Name = myToken2.Text, + Arguments = args + }; + } + } + } + } + else if(myToken.Type == "Identifier") + { + return { + Type = "IdentifierNode", + Text = myToken.Text + }; + } + else if(myToken.Type == "Text") + { + return { + Type = "TextNode", + Text = myToken.Text + }; + } + else if(myToken.Type == "Char") + { + return { + Type = "CharNode", + Text = $"\'{myToken.Text}\'" + }; + } + else if(myToken.Type == "String") + { + return { + Type = "StringNode", + Text = $"\"{myToken.Text}\"" + }; + } + else if(myToken.Type == "Equals" || myToken.Type == "OpenParen" || myToken.Type == "CloseParen" || myToken.Type == "Comma" || myToken.Type == "") + { + return { + Type = $"{myToken.Type}Node" + }; + } + } + return null; + } + + var nodes = []; + + while(i < tokens.Length) + { + nodes.Add(parse_node()); + } + return { + Type = "RootNode", + Nodes = nodes + }; +} + +func crossmarkupgen(ast) +{ + var page_functions = []; + + var code = ""; + + func add_to_page(name, code) + { + each(var item : page_functions) + { + if(item.Key == name) + { + item.Value += code; + return null; + } + } + page_functions.Add({ + Key = name, + Value = code + }); + } + + func generate_node(node) + { + func myescape(txt) + { + var out = ""; + each(var c : txt) + { + var cI = c.ToLong(); + if(cI < 32 || cI > 126) + { + out += $"\\x{(cI % 0xFF).ToHexString(2)}"; + } + else if(c == '\"') + { + out += "\\\""; + } + else if(c == '\'') + { + out += "\\\'"; + } + else if(c == '\\') + { + out += "\\\\"; + } + else { + out += c; + } + } + return out; + } + if(node.Type == "PageNode") + { + var code = $"if(ctx.Path == \"{node.Route}\")"; + code += "{__writer = ctx.OpenResponseStream(); "; + each(var a : node.Arguments) + { + code += $"var {a} = ctx.QueryParams.TryGetFirst(\"{a}\");"; + } + each(var item : node.Nodes) + { + code += generate_node(item); + } + code += " __writer.Close(); return true;}"; + + add_to_page(node.RouterFunction,code); + return ""; + } + else if(node.Type == "EmbedNode") + { + var code = $"if(ctx.Path == \"{node.Route}\")"; + code += "{"; + code += $"ctx.WithMimeType(Net.Http.MimeType(\"{node.Name}\")).SendBytes(embed(\"{node.Name}\"));"; + code += "return true;"; + code += "}"; + } + else if(node.Type == "TextNode") + { + return $"write(\"{myescape(node.Text)}\");"; + } + else if(node.Type == "ExprNode") + { + var code = "write("; + each(var item : node.Nodes) + { + code += generate_node(item); + } + code += ");"; + return code; + } + else if(node.Type == "CodeNode") + { + var code = ""; + each(var item : node.Nodes) + { + code += generate_node(item); + } + return code; + } + else if(node.Type == "ComponentNode") + { + var code = $"func {node.Name}(write,ctx"; + + each(var arg0 : node.Arguments) + { + code += $",{arg0}"; + } + code += "){"; + each(var n : node.Nodes) + { + code += generate_node(n); + } + code += "}"; + return code; + } + else if(node.Type == "UseComponentNode") + { + var code = $"{node.Name}(write,ctx"; + each(var arg : node.Arguments) + { + code += ","; + if(arg.Type == "ArgNode") + { + each(var itm : arg.Nodes) + { + code += generate_node(itm); + } + } + else if(arg.Type == "ArgComponentNode") + { + code += "(write,ctx"; + + each(var arg0 : arg.Arguments) + { + code += $",{arg0}"; + } + code += ")=>{"; + each(var n : arg.Nodes) + { + code += generate_node(n); + } + code += "}"; + } + } + code += ");"; + return code; + } + else if(node.Type == "CharNode") + { + return $" {node.Text} "; + } + else if(node.Type == "StringNode") + { + return $" {node.Text} "; + } + else if(node.Type == "IdentifierNode") + { + return $" {node.Text} "; + } + else if(node.Type == "OpenParenNode") + { + return " ( "; + } + else if(node.Type == "CloseParenNode") + { + return " ) "; + } + else if(node.Type == "CommaNode") + { + return " , "; + } + else if(node.Type == "EqualsNode") + { + return " = "; + } + else if(node.Type == "RootNode") + { + var code = ""; + + each(var item : node.Nodes) + { + if(item.Type != "TextNode") + code += generate_node(item); + } + + each(var pg : page_functions) + { + code += $"func {pg.Key}(ctx)"; + code += "{ ctx.WithMimeType(\"text/html\");"; + code += "var __writer = null;"; + + code += "func write(__text){ __writer.WriteText(__text); }"; + + code += pg.Value; + + code += "__writer.Close(); return false;}"; + } + + return code; + } + + return ""; + } + + return generate_node(ast); +} + +func EnumerateFiles(cfg,path) +{ + var txt = ""; + if(cfg.Project.DirectoryExists(path)) + each(var file : cfg.Project.EnumeratePaths(path)) + { + if(cfg.Project.RegularFileExists(file)) + { + var f = cfg.Project.OpenFile(file, "rb"); + var ms = FS.MemoryStream(true); + f.CopyTo(ms); + txt += ms.GetBytes().ToString(); + f.Close(); + ms.Close(); + } + else if(cfg.Project.DirectoryExists(file)) + { + EnumerateFiles(cfg, file); + } + } + return txt; +} + +func RunTool(cfg) +{ + var text = ""; + text += EnumerateFiles(cfg, "/components"); + text += EnumerateFiles(cfg, "/pages"); + var c = crossmarkuplexer(text); + + var r = crossmarkupparser(c); + + var src = crossmarkupgen(r); + + cfg.GeneratedSource.Add({Source = src, FileName="markup.tcross"}); +} \ No newline at end of file diff --git a/Tesses.CrossLang.PackageServer/cross.json b/Tesses.CrossLang.PackageServer/cross.json new file mode 100644 index 0000000..30270be --- /dev/null +++ b/Tesses.CrossLang.PackageServer/cross.json @@ -0,0 +1,10 @@ +{ + "name": "Tesses.CrossLang.PackageServer", + "version": "1.0.0.0-prod", + "project_dependencies": [ + "./Tesses.CrossLang.Markup" + ], + "info": { + "type": "console" + } +} \ No newline at end of file diff --git a/Tesses.CrossLang.PackageServer/pages/index.tcrml b/Tesses.CrossLang.PackageServer/pages/index.tcrml new file mode 100644 index 0000000..7a6da2a --- /dev/null +++ b/Tesses.CrossLang.PackageServer/pages/index.tcrml @@ -0,0 +1,3 @@ + +

Welcome to the package server

+ \ No newline at end of file diff --git a/Tesses.CrossLang.PackageServer/src/program.tcross b/Tesses.CrossLang.PackageServer/src/program.tcross new file mode 100644 index 0000000..dd42bf8 --- /dev/null +++ b/Tesses.CrossLang.PackageServer/src/program.tcross @@ -0,0 +1,4 @@ +func main(args) +{ + Net.Http.ListenSimpleWithLoop(Router,4200); +} \ No newline at end of file diff --git a/Tesses.CrossLang.Shell/cross.json b/Tesses.CrossLang.Shell/cross.json new file mode 100644 index 0000000..8747f15 --- /dev/null +++ b/Tesses.CrossLang.Shell/cross.json @@ -0,0 +1,14 @@ +{ + "name": "Tesses.CrossLang.Shell", + "version": "1.0.0.0-prod", + "info": { + "maintainer": "Mike Nolan", + "type": "console", + "repo": "https://gitea.site.tesses.net/tesses50/crosslang/crosslang-libs", + "homepage": "https://crosslang.tesseslanguage.com/", + "license": "LGPLv3" + }, + "project_dependencies": [ + "./Tesses.CrossLang.BuildEssentials" + ] +} \ No newline at end of file diff --git a/Tesses.CrossLang.Shell/src/main.tcross b/Tesses.CrossLang.Shell/src/main.tcross new file mode 100644 index 0000000..d293a86 --- /dev/null +++ b/Tesses.CrossLang.Shell/src/main.tcross @@ -0,0 +1,4 @@ +func main(args) +{ + Console.WriteLine("Hello, world"); +} \ No newline at end of file diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..cc1f786 --- /dev/null +++ b/install.sh @@ -0,0 +1 @@ +#!/bin/bash \ No newline at end of file diff --git a/newtonsoft_json_config_schema.cs b/newtonsoft_json_config_schema.cs new file mode 100644 index 0000000..10c859e --- /dev/null +++ b/newtonsoft_json_config_schema.cs @@ -0,0 +1,48 @@ +using System; +using System.IO; +using Newtonsoft.Json; +using System.Collections.Generic; +namespace Tesses.CrossLang +{ + public class ProjectFile + { + public string name {get;set;}=""; + public string version {get;set;}=""; + + public string resource_directory {get;set;}="res"; //defaults to res, this is the resource directory used for embed("filename")) + + + public string source_directory {get;set;}="src"; //defaults to src, used for storing sourcecode + + public string bin_directory {get;set;}="bin"; //defaults to bin, used for storing output + + public string obj_directory {get;set;}="obj"; //defaults to obj, used for storing compile tools + + public List project_dependencies {get;set;}=new List(); + + public List dependencies {get;set;}=new List(); + + public ProjectInfo info {get;set;}=new ProjectInfo(); + } + public class Dependency { + public string name {get;set;}=""; + + public string version {get;set;}=""; + } + public class ProjectInfo //this is stored in crvm file as JSON in INFO as well (with index in STRS table) + { + public string maintainer {get;set;}=""; //Not checked when building project + public string type {get;set;}=""; //gets checked whether it is compile_tool by build tool, possible values are in file: project_types.txt + public string repo {get;set;}=""; //optional, is the place where the code is stored + public string homepage {get;set;}=""; //optional, is the website for the project + + public string license {get;set;}=""; //optional, but recommended to tell people what the license is + + public string readme {get;set;}=""; //optional but tells people about the package + } + + public static void Main(string[] args) + { + var project = JsonConvert.DeserializeObject(File.ReadAllText("config.json")); + } +} \ No newline at end of file diff --git a/project_types.txt b/project_types.txt new file mode 100644 index 0000000..0b39801 --- /dev/null +++ b/project_types.txt @@ -0,0 +1,6 @@ +console: a console application (or webserver) +lib: a library +app: a gui app (used for eventual gui system) +template: used for project templates +compile_tool: run before source is compiled for project if it is in the dependency tree for the project (and is not linked to said projects) +tool: a tool invokable via crosslang \ No newline at end of file diff --git a/script.sh b/script.sh new file mode 100755 index 0000000..416e3a5 --- /dev/null +++ b/script.sh @@ -0,0 +1,3 @@ +#!/bin/bash +cd Tesses.CrossLang.BuildEssentials && crossc -o ./bin-tmp -n Tesses.CrossLang.BuildEssentials -v 1.0.0.0-prod main.tcross src/*.tcross && cd .. +crossvm ./Tesses.CrossLang.BuildEssentials/bin-tmp/Tesses.CrossLang.BuildEssentials-1.0.0.0-prod.crvm Tesses.CrossLang.Shell \ No newline at end of file