commit 53bbd6164235dba7bc3a2d15e686745c47a8e4db Author: Mike Nolan Date: Fri May 9 12:48:33 2025 -0500 First commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60b2f55 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +public +.hugo_build.lock \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..5c05f90 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "themes/hugo-theme-relearn"] + path = themes/hugo-theme-relearn + url = https://github.com/McShelby/hugo-theme-relearn.git diff --git a/archetypes/default.md b/archetypes/default.md new file mode 100644 index 0000000..c6f3fce --- /dev/null +++ b/archetypes/default.md @@ -0,0 +1,5 @@ ++++ +title = '{{ replace .File.ContentBaseName "-" " " | title }}' +date = {{ .Date }} +draft = true ++++ diff --git a/content/_index.md b/content/_index.md new file mode 100644 index 0000000..ef36c7a --- /dev/null +++ b/content/_index.md @@ -0,0 +1,26 @@ ++++ +title = "CrossLang" +type = "home" ++++ + +> :warning: **NOT READY FOR PRODUCTION (THERE WILL BE BREAKING CHANGES)** + +My dynamic programming language + +## Essential Links + +- [Linux](https://crosslang.tesseslanguage.com/download/crosslang-x86_64.tar.gz) +- [Windows](https://crosslang.tesseslanguage.com/download/crosslang-win32.exe) +- [Windows Portable](https://crosslang.tesseslanguage.com/download/crosslang-win32.zip) +- [ISO](https://crosslang.tesseslanguage.com/download/crosslang.iso) +- [More Binaries](https://crosslang.tesseslanguage.com/download/) +- [Packages](https://cpkg.tesseslanguage.com/) +- [Source](https://onedev.site.tesses.net/crosslang) + + +``` +Ye are of God, little children, and have overcome them: because greater is he that is in you, than he that is in the world. (1 John 4:4) +``` + + +Language License is [GPLv3](https://onedev.site.tesses.net/crosslang/~files/master/LICENSE.md) \ No newline at end of file diff --git a/content/language-features/_index.md b/content/language-features/_index.md new file mode 100644 index 0000000..2d0c44c --- /dev/null +++ b/content/language-features/_index.md @@ -0,0 +1,7 @@ ++++ +title = "Language Features" +type = "chapter" +weight = 2 ++++ + +- [The basics](basics.md) \ No newline at end of file diff --git a/content/language-features/basics.md b/content/language-features/basics.md new file mode 100644 index 0000000..a11a164 --- /dev/null +++ b/content/language-features/basics.md @@ -0,0 +1,585 @@ ++++ +title = 'The basics' +date = 2025-05-08T22:23:44-05:00 ++++ + +This is a book for my language found [here](https://crosslang.tesseslanguage.com/) + + + +## Statements and loops + + + +#### Declare a variable (it is an expression) + +You can (the var is optional but should be used if the root environment has the same variable and you don't want to set it) + +```js +var myVariable = 42; +``` + +#### Set a variable (it is an expression) + +```js +myVariable = "I have set the variable to a string"; +``` + +#### If statements + +The {} are optional if you only need one statement + +```js +var myExpression = 0; +var myOtherExpression = { + mol = 42 +}; + +if(myExpression) +{ + Console.WriteLine("myExpression is truthy"); +} +else if(myOtherExpression) +{ + //this will run based on the condition + Console.WriteLine("myExpression is falsey but myOtherExpression is truthy"); +} +else { + Console.WriteLine("both myExpression and myOtherExpression are falsey"); +} +``` + +#### For loop + +Note: i will leak, also you can use curly brackets like if + +```js +for(var i = 0; i < 42; i++) + Console.WriteLine(i); +``` + +#### Each loop + +```js +enumerable MyItterator() +{ + yield 42; + yield 100; + yield 88; +} +each(var item : MyItterator()) +{ + Console.WriteLine(item); +} + + +each(var item : [3,7,12]) +{ + Console.WriteLine(item); +} + + +/* + This should output + 42 + 100 + 88 + 3 + 7 + 12 +*/ +``` + +#### While loop + +```js +while(conditionLikeIf) +{ + Console.WriteLine("Hi"); +} + +//If conditionLikeIf is falsey we never print Hi +//If conditionLikeIf is truthy we print Hi until it is falsey +``` + +#### Do loop + +```js +do(conditionLikeIf) +{ + Console.WriteLine("Hi"); +} + +//If conditionLikeIf is falsey we print Hi once +//If conditionLikeIf is truthy we print Hi until it is falsey +``` + + + +#### Try statement + +Note: you can't yield, return, break or continue from inside a try statement (also applys to catch and finally due to these being internally closures) + +```js +try { + Console.WriteLine("God is good."); + throw "my error"; + Console.WriteLine("I am lonely, I am never called."); +} +catch(ex) +{ + Console.WriteLine($"I got an error {ex}."); +} +finally { + Console.WriteLine("For God so loved the world that he gave his only begotten Son, that whoever believes in him should not perish but have eternal life."); +} + + +/* + This should print + God is good. + I got an error my error. + For God so loved the world that he gave his only begotten Son, that whoever believes in him should not perish but have eternal life. +*/ +``` + +#### Switch statement + +NOTE: you can use dictionaries with overloaded equals operator (we will pass the switch's expression as the argument) + +```js +o = { + operator== = (this,v) => { + //this is implicitly passed by runtime, but you must declare it if you want it + return (v * 7) == 42; + } +}; + +var val = 6; + +switch(val) +{ + case 4: + Console.WriteLine("I am four"); + break; + case 5: + Console.WriteLine("I am five"); + break; + case o: + Console.WriteLine("Hitchhiker's guide to the galaxy meaning of life"); + break; + default: + Console.WriteLine("We don't support it we are sorry"); +} +``` + + + +#### Function declaration + +```go +//you can create functions on dictionaries so long as they are on root environment (they are declared there before root scope is evaluated so this is possible) +My.Func.Joel = 59; //Because My.Func.Is.A.Few.Deep creates the dictionaries via runtime + +func My.Func.Is.A.Few.Deep(a, b) +{ + return a * b; +} +func main(args) +{ + Console.WriteLine(My.Func.Is.A.Few.Deep(6,7)); +} +``` + +#### Function inside a function + +Oh yeah functions can have exclusively a expression as a body which does not need a return keyword + +```go +func main(args) +{ + func MyOther(a,b) a * b; + Console.WriteLine(MyOther(a,b)); +} +``` + +#### Document a function + +```go +/^ + This function returns 42 +^/ +func MyFunction() 42; +``` + +#### Return statement + +You can also return nothing + +```js +return 42; +return; +``` + +#### Yield statement + +This will halt the function's execution and return the running function object (were you can pop the item and resume it) + +To automaticly make a function enumerable (with each statement) you must use ``enumerable`` instead of func when declaring your function + +```js +yield 42; +``` + +#### Throw statement + +You can catch this with ``try statement`` with ``catch`` clause + +```js +throw "You can replace me with another string or any other object"; +``` + +#### Defer statement + +Your code will be called when your scope is destroyed + +```go +{ + defer { + Console.WriteLine("In defer"); + } + Console.WriteLine("About to leave scope"); +} +Console.WriteLine("Left scope"); + + +/* +The output should be + +About to leave scope +In defer +Left scope +*/ +``` + +## Expressions + +We will place it as a parameter to a function ``doThing`` but these will work anywhere like setting a variable or another expression + +#### Undefined + +```js +doThing(undefined); +``` + +#### Null + +```js +doThing(null); +``` + +#### Boolean + +```js +doThing(false); +doThing(true); +``` + +#### Long + +A signed 64 bit number + +```js +doThing(94); +doThing(599929022); +``` + +#### Double + +A 64 bit floating pointer number + +```js +doThing(5.25); +doThing(942.90204); +``` + +#### Char + +Yes we support single character strings (this escapes a double quote) + +```csharp +doThing('\"'); +``` + +#### String + +Second is an interopolated string + +```csharp +doThing("Hi"); +doThing($"My name is {name}"); +``` + +#### List + +```js +doThing( + [4,5,9,42,true,"Hi",'\n'] +); +``` + +#### Dictionary + +```js +doThing( + { + a = "This is an option", + b = 42, + c = 9 + } +); +``` + +###### Enumerating a dictionary + +```js +var dict = { a = 5, b = 42}; +each(var item : Dictionary.Items(dict)) +{ + Console.WriteLine($"Key: {item.Key}"); + Console.WriteLine($"Value: {item.Value}"); + Console.WriteLine(); +} +/* +This prints +Key: a +Value: 5 + +Key: b +Value: 42 + +*/ +``` + + + +###### Getting a value from dictionary + +```go +func doThing(data) +{ + Console.WriteLine(data.b); //will print 42 +} +``` + +###### Setting a value to dictionary + +```go +func doThing(data) +{ + data.a = true; //replace a with a different value + data.someFieldThatDoesNotExist = 9; //define a new field entirely + +} +``` + +###### Methods + +Note that this is optional but if you do have it it must be the first argument, the this argument points to the dictionary + +```go +var item = { + myMethod = (this, a, b) => { + return a * b; + } +}; + +Console.WriteLine(item.myMethod(6,7)); //prints 42 +``` + +Or + +```go +var item = {}; +func item.myMethod(this, a, b) +{ + return a * b; +} +Console.WriteLine(item.myMethod(6,7)); //prints 42 +``` + +###### Properties + +They are declared like every other method except they are prefixed with ``get`` or ``set`` + +```go +var item = { + getProp = (this)=>{ + return 42; + }, + setProp = (this,v)=>{ + //do something with v + } +}; + +Console.WriteLine(item.Prop); //equivalent to Console.WriteLine(item.getProp()); + +item.Prop = 100; //equivalent to item.setProp(100); will do nothing in this example + +``` + +###### Operator overloading + +```js +var item = { + operator+ = (this,right) => { + return 4 + a; + } + operator- = (this,right) => { + return 4 - right; //be careful right may be undefined if the negate operator is used + } +}; + +Console.WriteLine(item + 5); //prints 9 +``` + +###### Array operator overloading + +```js +var item = { + GetAt = (index)=>{ + return index * 2; //we multiply index by two and return + }, + SetAt => (index,value)=>{ + Console.WriteLine($"The index was {index} and value was {value}"); + } +}; + +Console.WriteLine(item[21]); //prints 42 +item["Hi"] = "John"; //prints The index was Hi and value was John +``` + +#### ByteArray + +```js +var bA = new ByteArray(1); +ba[0] = 42; +Console.WriteLine(ba.ToString()); //prints * +``` + +###### ByteArray from string + +```js +var bA = new ByteArray("Hi"); +//we can get bytes like this bA[0] which will be 72 +//we can get length by bA.Count or bA.Length +``` + +#### Embedding files (you can't do this easily in C/C++ and C# not as easy as this) + +```js +var bA = embed("myFile.png"); //will embed the file res/myFile.png +//it is stored as a RESO in the crvm file and bA is a ByteArray +//note the argument MUST be a constant string +//note you can access a subdirectory of res as well just use dir/file.bin +``` + +#### Streams + + + +###### From an existing file + +```js +var strm = FS.Local.OpenFile("file.bin","rb"); + +var data = new ByteArray(1024); +var read = strm.Read(data,0,data.Count); +//use ReadBlock to ensure you have 1024 bytes if not near end of stream + +//use WriteBlock to ensure you write the amount you say you need + +strm.Close(); +``` + +#### VFS + +```js +var myVFS = FS.Local; //FS.Local is the local filesystem + + +myVFS.CreateDirectory("myDir"); //creates directory in current dir (only local) + +myVFS.DeleteDirectory("myDir"); //now we delete it + + +myVFS.CreateDirectory(Path.FromString(Env.Downloads) / "Folder in Downloads"); //Create a folder in downloads +``` + + + +#### Path + +```js +var path = / "Path" / "To" / "Directory"; +var relativePath = ./"another"/"path"; +var combined = path / relativePath; +var someString = "joel"; +var combinedAndStr = combined / someString; +var combinedWithExtension = combined + ".mp4"; +Console.WriteLine(combined); // outputs /Path/To/Directory/another/path +Console.WriteLine(combined); // outputs /Path/To/Directory/another/path/joel +Console.WriteLine(combinedWithExtension); //outputs /Path/To/Directory/another/path.mp4 +//these paths are used with vfs + + +//to get parent directory use combined.GetParent(); +//to get filename use combined.GetFileName(); +//to get extension use combinedWithExtension.GetExtension();, it will be the extension including . +//to change the extension use combinedWithExtension.ChangeExtension(".mkv"); +//to remove the extension use combinedWithExtension.ChangeExtension(null); or combinedWithExtension.ChangeExtension(); +``` + +#### Html Litterals +```go +//comments are just crosslang ones + +//we will be setting to myHtml for the html (returns a string) (it is already html escaped) +myHtml =

{someStringExpression}

; + +//a link, in this example we have a dictionary named node with string fields href and text +//lets say node.text equaled List and href contained ./mypage?name=Joel&file=steve.bin myHtml would be equal to "List<int>" (the \ are just there to make this a valid string for demonstration purposes, there aren't really backslashes) +myHtml = {node.text}; + + +//for (works like for loop but is in html form, the for part is not rendered in the final string) +myHtml = +
{i}
+ ; + +//each +myHtml = ; + +//do +myHtml = ; + +//while +myHtml = ; + +//if + +myHtml = + + //if expr is 42 + + + //if expr is not 42 + //you would use another if here instead of else if + +; + +myHtml = Hello; //would just be Hello (useful for templating as it works just like div but the null part is not emited into string) + +myHtml = ; //allowing you to emit unescaped html from string into html litteral (useful for templating) +``` + diff --git a/content/language-features/creating-a-project.md b/content/language-features/creating-a-project.md new file mode 100644 index 0000000..c32ebbe --- /dev/null +++ b/content/language-features/creating-a-project.md @@ -0,0 +1,16 @@ ++++ +title = 'Creating a project' +date = 2025-05-08T22:23:44-05:00 ++++ + +### Console application + +```bash +mkdir proj_name +cd proj_name +crosslang new console + +# edit the src/main.tcross + +crosslang run +``` \ No newline at end of file diff --git a/content/language-features/working-with-files.md b/content/language-features/working-with-files.md new file mode 100644 index 0000000..a1b595e --- /dev/null +++ b/content/language-features/working-with-files.md @@ -0,0 +1,44 @@ ++++ +title = 'Working with files' +date = 2025-05-08T22:23:44-05:00 ++++ + +## Write text to file +```go +FS.WriteAllText(FS.Local, "file.txt", "Some text"); +``` + +## Read text from file +```go +var text = FS.ReadAllText(FS.Local, "file.txt"); +``` + +## Create a directory +```go +FS.Local.CreateDirectory("New Folder"); +FS.Local.CreateDirectory("Folder" / "Another Folder"); // we can create folders even if parents don't exist +``` + +## Enumerating entries in folder +```go +each(var file : FS.Local.EnumeratePaths(/)) +{ + if(FS.Local.DirectoryExists(file)) Console.Write("DIR "); + + Console.WriteLine(file); +} +``` + +### Exists +```go +FS.Local.FileExists("/path/to/file"); //use FS.Local.RegularFileExists("/path/to/file"); if you don't want special files to be considered +FS.Local.DirectoryExists("/path/to/directory"); +``` + +### Opening files +See [Streams](streams.md) for more details on the Stream object +```go +var strm = FS.Local.OpenFile("/path/to/file.bin", "rb"); +//use strm.Read(buffer,buffer_offset,length); to read some data, returns number of bytes read +strm.Close(); +``` diff --git a/hugo.toml b/hugo.toml new file mode 100644 index 0000000..2365af4 --- /dev/null +++ b/hugo.toml @@ -0,0 +1,4 @@ +baseURL = 'https://crosslang.tesseslanguage.com/' +languageCode = 'en-us' +title = 'CrossLang' +theme = 'hugo-theme-relearn' diff --git a/static/images/favicon.svg b/static/images/favicon.svg new file mode 100644 index 0000000..e92a662 --- /dev/null +++ b/static/images/favicon.svg @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/themes/hugo-theme-relearn b/themes/hugo-theme-relearn new file mode 160000 index 0000000..0b83617 --- /dev/null +++ b/themes/hugo-theme-relearn @@ -0,0 +1 @@ +Subproject commit 0b83617ee9da5253aafcf11807b256da7d88d709