{"id":44855547,"url":"https://github.com/x-research-team/vm","last_synced_at":"2026-02-17T07:54:26.898Z","repository":{"id":57564024,"uuid":"322601334","full_name":"x-research-team/vm","owner":"x-research-team","description":"Virtual Machine","archived":false,"fork":false,"pushed_at":"2021-07-03T16:12:08.000Z","size":51090,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2023-07-27T22:48:50.752Z","etag":null,"topics":["compiler","interpreter","interpreter-language","vm"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/x-research-team.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-12-18T13:21:47.000Z","updated_at":"2023-01-29T03:57:35.000Z","dependencies_parsed_at":"2022-08-31T13:42:19.779Z","dependency_job_id":null,"html_url":"https://github.com/x-research-team/vm","commit_stats":null,"previous_names":[],"tags_count":1,"template":null,"template_full_name":null,"purl":"pkg:github/x-research-team/vm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/x-research-team%2Fvm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/x-research-team%2Fvm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/x-research-team%2Fvm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/x-research-team%2Fvm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/x-research-team","download_url":"https://codeload.github.com/x-research-team/vm/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/x-research-team%2Fvm/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29536934,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-17T05:00:25.817Z","status":"ssl_error","status_checked_at":"2026-02-17T04:57:16.126Z","response_time":100,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["compiler","interpreter","interpreter-language","vm"],"created_at":"2026-02-17T07:54:26.125Z","updated_at":"2026-02-17T07:54:26.886Z","avatar_url":"https://github.com/x-research-team.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n    \u003cimg alt=\"vm language logo\" src=\"https://github.com/haifenghuang/vm/blob/master/vm.png?raw=true\" width=\"310\"\u003e\n\u003c/p\u003e\n\n# VM Programming Language\n\n## Summary\n\nVM is a toy language interpreter, written in Go. It has C-style syntax, and is largely\ninspired by Ruby, Python, Perl and c#.\n\nIt support the normal control flow, functional programming and object oriented programming.\nand also can import golang's module.\n\nIt has a built-in documentation generator(mdoc) for generating html document from vm source.\n\nIt has a simple debugger which you can experience with it.\n\nIt also has a REPL with realtime syntax highlighter.\n\nI also made a simple programming language written using `vm`.\n\nYou can even run most of the `vm` script in a web browser.\n\n## Documention\n\nComplete language tutorial can be found in [docs](docs)\n\n## Features\n\n* Class with support for property, indexer \u0026 operator overloading\n* await/async for asynchronous programming\n* Builtin support for linq\n* Builtin support for datetime literal\n* First class function\n* function with Variadic parameters and default values\n* function with multiple return values\n* int, uint, float, bool, array, tuple, hash(all support json marshal \u0026 unmarshal, all can be extended)\n* try-catch-finally exception handling\n* Optional Type support(Java 8 like)\n* using statment(C# like)\n* Elixir like pipe operator\n* Using method of Go Package(RegisterFunctions and RegisterVars)\n* Syntax-highlight REPL\n* Doc-generation tool `mdoc`\n* Integrated services processing\n* Simple debugger\n* Simple Macro processing\n\n## Example1(Linq)\n\n```csharp\n// async/await\nasync fn add(a, b) { a + b }\n\nresult = await add(1, 2)\nprintln(result)\n\n// linq example\nclass Linq {\n    static fn TestSimpleLinq() {\n        //Prepare Data Source\n        let ingredients = [\n            {Name: \"Sugar\",  Calories: 500},\n            {Name: \"Egg\",    Calories: 100},\n            {Name: \"Milk\",   Calories: 150},\n            {Name: \"Flour\",  Calories: 50},\n            {Name: \"Butter\", Calories: 200},\n        ]\n\n        //Query Data Source\n        ingredient = from i in ingredients where i.Calories \u003e= 150 orderby i.Name select i\n\n        //Display\n        for item in ingredient =\u003e println(item)\n    }\n\n    static fn TestFileLinq() {\n        //Read Data Source from file.\n        file = newFile(\"./examples/linqSample.csv\", \"r\")\n\n        //Query Data Source\n        result = from field in file where int(field[1]) \u003e 300000 select field[0]\n\n        //Display\n        for item in result =\u003e printf(\"item = %s\\n\", item)\n\n        file.close()\n    }\n\n    /* Code from https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/let-clause */\n    static fn TestComplexLinq() {\n        //Data Source\n        stringList = [\n            \"A penny saved is a penny earned.\",\n            \"The early bird catches the worm.\",\n            \"The pen is mightier than the sword.\"\n        ]\n\n        //Query Data Source\n        earlyBirdQuery =\n            from sentence in stringList\n            let words = sentence.split(\" \")\n            from word in words\n            let w = word.lower()\n            where w[0] == \"a\" || w[0] == \"e\" ||\n                  w[0] == \"i\" || w[0] == \"o\" ||\n                  w[0] == \"u\"\n            select word\n\n        //Display\n        for v in earlyBirdQuery =\u003e printf(\"'%s' starts with a vowel\\n\", v)\n    }\n}\n\nLinq.TestSimpleLinq()\nprintln(\"======================================\")\nLinq.TestFileLinq()\nprintln(\"======================================\")\nLinq.TestComplexLinq()\n```\n\n## Example2(Rest Service)\n\n```csharp\n//service Hello on \"0.0.0.0:8090\" {\nservice Hello on \"0.0.0.0:8090:debug\" { //':debug': for debugging request\n  //In '@route', you could use 'url(must), methods, host, schemes, headers, queries'\n  @route(url=\"/authentication/login\", methods=[\"POST\"])\n  fn login(writer, request) {\n    //writer.writeJson({ sessionId: \"3d5bd2cA15ef047689\" })\n    //writer.writeJson({ sessionId: \"3d5bd2cA15ef047689\" }), 200 # same as above\n    //return { sessionId: \"3d5bd2cA15ef047689\" }, 200 # same as above\n    return { sessionId: \"3d5bd2cA15ef047689\" } // same as above\n  }\n\n  @route(url=\"/authentication/logout\", methods=[\"POST\"])\n  fn logout(writer, request) {\n    // writer.writeHeader(http.STATUS_CREATED) # return http status code 201\n    return http.STATUS_CREATED // same as above\n  }\n\n  @route(url=\"/meters/setting-result/{acceptNo}\", methods=[\"GET\"])\n  fn load_survey_result(writer, request) {\n    //using 'vars' dictionary to access the url parameters\n    //writer.writeJson({ acceptNo: vars[\"acceptNo\"], resultCode: \"1\"})\n    return { acceptNo: vars[\"acceptNo\"], resultCode: \"1\"} // same as above\n  }\n\n  @route(url=\"/articles/{category}/{id:[0-9]+}\", methods=[\"GET\"])\n  fn getArticle(writer, request) {\n    //using 'vars' dictionary to access the url parameters\n    //writer.writeJson({ category: vars[\"category\"], id: vars[\"id\"]})\n    return { category: vars[\"category\"], id: vars[\"id\"]} // same as above\n  }\n}\n```\n\n## Getting started\n\nBelow demonstrates some features of the VM language:\n\n### Basic\n\n```csharp\ns1 = \"hello, 黄\"       // strings are UTF-8 encoded\n三 = 3                 // UTF-8 identifier\ni = 20_000_000         // int\nu = 10u                // uint\nf = 123_456.789_012    // float\nb = true               // bool\na = [1, \"2\"]           // array\nh = {\"a\": 1, \"b\": 2}   // hash\nt = (1,2,3)            // tuple\ndt = dt/2018-01-01 12:01:00/  //datetime literal\nn = nil\n```\n\n### Const\n\n```csharp\nconst PI = 3.14159\nPI = 3.14 //error\n\nconst (\n    INT,    //default to 0\n    DOUBLE,\n    STRING\n)\nlet i = INT\n```\n\n### Enum\n\n```csharp\nLogOption = enum {\n    Ldate         = 1 \u003c\u003c 0,\n    Ltime         = 1 \u003c\u003c 1,\n    Lmicroseconds = 1 \u003c\u003c 2,\n    Llongfile     = 1 \u003c\u003c 3,\n    Lshortfile    = 1 \u003c\u003c 4,\n    LUTC          = 1 \u003c\u003c 5,\n    LstdFlags     = 1 \u003c\u003c 4 | 1 \u003c\u003c 5\n}\n\nopt = LogOption.LstdFlags\nprintln(opt)\n```\n\n### Control Flow\n\n* if\n* for\n* while\n* do\n* case-in\n\n#### if\n\n```csharp\n//if\nlet a, b = 10, 5\nif (a \u003e b) {\n    println(\"a \u003e b\")\n}\nelif a == b {\n    println(\"a = b\")\n}\nelse {\n    println(\"a \u003c b\")\n}\n\nif 10.isEven() {\n    println(\"10 is even\")\n}\n\nif 9.isOdd() {\n    println(\"9 is odd\")\n}\n```\n\n#### for\n\n```csharp\ni = 9\nfor { // forever loop\n    i = i + 2\n    if (i \u003e 20) { break }\n    println('i = {i}')\n}\n\ni = 0\nfor (i = 0; i \u003c 5; i++) {  // c-like for, '()' is a must\n    if (i \u003e 4) { break }\n    if (i == 2) { continue }\n    println('i is {i}')\n}\n\n# for x in arr \u003cwhere expr\u003e {}\nlet a = [1,2,3,4]\nfor i in a where i % 2 != 0 {\n    println(i)\n}\n\n# read line by line\nusing (f = open(\"./file.log\", \"r\")) {\n    for line in \u003c$f\u003e where line =~ ``vm`` {\n        println(line) //print only lines which match 'vm'\n    }\n}\n```\n\n#### while\n\n```csharp\ni = 10\nwhile (i\u003e3) {\n    i--\n    println('i={i}')\n}\n\n# read line by line\nusing (f = open(\"./file.log\", \"r\")) {\n    while \u003c$f\u003e {\n        println($_) //$_: line read from file\n    }\n}\n```\n\n#### do\n\n```csharp\ni = 10\ndo {\n    i--\n    if (i==3) { break }\n}\n```\n\n#### case-in\n\n```csharp\nlet i = [{\"a\": 1, \"b\": 2}, 10]\nlet x = [{\"a\": 1, \"b\": 2},10]\ncase i in {\n    1, 2 { println(\"i matched 1, 2\") }\n    3    { println(\"i matched 3\") }\n    x    { println(\"i matched x\") }\n    else { println(\"i not matched anything\")}\n}\n```\n\n### Array\n\n```csharp\na = [1,2,3,4]\nfor i in a where i % 2 != 0 {\n    println(i)\n}\n\nif ([].empty()) {\n    println(\"array is empty\")\n}\n\na.push(5)\n\nrevArr = reverse(a)\nprintln(\"Reversed Array = \", revArr)\n```\n\n### Hash\n\n```csharp\nhashObj = {\n    12     : \"twelve\",\n    true   : 1,\n    \"Name\" : \"HHF\"\n}\nprintln(hashObj)\n\nhashObj += {\"key1\" : \"value1\"}\nhashObj -= \"key1\"\nhashObj.push(15, \"fifteen\") //first parameter is the key, second is the value\n\nhs = {\"a\": 1, \"b\": 2, \"c\": 3, \"d\": 4, \"e\": 5, \"f\": 6, \"g\": 7}\nfor k, v in hs where v % 2 == 0 {\n    println('{k} : {v}')\n}\n\ndoc = {\n    \"one\": {\n        \"two\":  { \"three\": [1, 2, 3], \"six\":(1,2,3)},\n        \"four\": { \"five\":  [11, 22, 33]},\n    },\n}\n\n// same as below\n//doc[one][two][three][2] = 44\ndoc[\"one\"][\"two\"][\"three\"][2] = 44\nprintf(\"doc[one][two][three][2]=%v\\n\", doc[\"one\"][\"two\"][\"three\"][2])\n\ndoc.one.four.five = 4\nprintf(\"doc.one.four.five=%v\\n\", doc.one.four.five)\n```\n\n### Tuple\n\n```csharp\nt = () //same as 't = tuple()'\n\nfor i in (1,2,3) {\n    println(i)\n}\n```\n\n### datetime literal\n\n```csharp\nlet month = \"01\"\nlet dt0 = dt/2018-{month}-01 12:01:00/\nprintln(dt0)\n\nlet dt1 = dt/2018-01-01 12:01:00/.addDate(1, 2, 3).add(time.SECOND * 10) //add 1 year, two months, three days and 10 seconds\nprintf(\"dt1 = %v\\n\", dt1)\n\n/* 'datetime literal' + string:\n     string support 'YMDhms' where\n       Y:Year    M:Month    D:Day\n       h:hour    m:minute   s:second\n\n*/\n//same result as 'dt1'\nlet dt2 = dt/2018-01-01 12:01:00/ + \"1Y2M3D10s\" //add 1 year, two months, three days and 10 seconds\nprintf(\"dt2 = %v\\n\", dt2)\n//same resutl as above\n//printf(\"dt2 = %s\\n\", dt2.toStr()) //use 'toStr()' method to convert datetime to string.\n\nlet dt3 = dt/2019-01-01 12:01:00/\n//you could also use strftiem() to convert time object to string. below code converts time object to 'yyyy/mm/dd hh:mm:ss'\nformat = dt3.strftime(\"%Y/%m/%d %T\")\nprintln(dt3.toStr(format))\n\n////////////////////////////////\n// time object to timestamp\n////////////////////////////////\nprintln(dt3.unix()) //to timestamp(UTC)\nprintln(dt3.unixNano()) //to timestamp(UTC)\nprintln(dt3.unixLocal()) //to timestamp(LOCAL)\nprintln(dt3.unixLocalNano()) //to timestamp(LOCAL)\n\n////////////////////////////////\n// timestamp to time object\n////////////////////////////////\ntimestampUTC = dt3.unix()      //to timestamp(UTC)\nprintln(unixTime(timestampUTC)) //timestamp to time\n\ntimestampLocal = dt3.unixLocal() //to timestamp(LOCAL)\nprintln(unixTime(timestampLocal)) //timestamp to time\n\n////////////////////////////////\n// datetime comparation\n////////////////////////////////\n//two datetime literals could be compared using '\u003e', '\u003e=', '\u003c', '\u003c=' and '=='\nlet dt4 = dt/2018-01-01 12:01:00/\nlet dt5 = dt/2019-01-01 12:01:00/\n\nprintln(dt4 \u003c= dt5) //returns true\n```\n\n### Regular expression\n\nIn vm, regard to regular expression, you could use:\n\n* Regular expression literal\n* 'regexp' module\n* =\u0026#126; and !\u0026#126; operators(like perl's)\n\n```swift\n//Use regular expression literal( /pattern/.match(str) )\nlet regex = /\\d+\\t/.match(\"abc 123\tmnj\")\nif (regex) { println(\"regex matched using regular expression literal\") }\n\n//Use 'regexp' module\nif regexp.compile(``\\d+\\t``).match(\"abc 123\tmnj\") {\n    println(\"regex matched using 'regexp' module\")\n}\n\n//Use '=~'(str =~ pattern)\nif \"abc 123\tmnj\" =~ ``\\d+\\t`` {\n    println(\"regex matched using '=~'\")\n}else {\n    println(\"regex not matched using '=~'\")\n}\n```\n\n### Conversion\n\n```csharp\n// convert to string using str() function\nx = str(10) // convert 10 to string  \n\n// convert to int using int() function\nx1 = int(\"10\")   // x1 = 10\nx2 = +\"10\" // same as above\n\ny1 = int(\"0x10\") // y1 = 16\ny2 = +\"0x10\" // same as above\n\n// convert to float using float() funciton\nx = float(\"10.2\")\n\n// convert to array using array() funciton\nx = array(\"10\") // x = [\"10\"]\ny = array((1, 2, 3)) // convert tuple to array\n\n// convert to tuple using tuple() funciton\nx = tuple(\"10\") // x = (\"10\",)\ny = tuple([1, 2, 3]) // convert array to tuple\n\n// convert to hash using hash() function\nx = hash([\"name\", \"jack\", \"age\", 20]) // array-\u003ehash: x = {\"name\" : \"jack\", \"age\" : 20}\ny = hash((\"name\", \"jack\", \"age\", 20)) // tuple-\u003ehash: x = {\"name\" : \"jack\", \"age\" : 20}\n\n// if the above conversion functions have no arguments, they simply return\n// new corresponding types\ni = int()   // i = 0\nf = float() // f = 0.0\ns = str()   // s = \"\"\nh = hash()  // h = {}\na = array() // a = []\nt = tuple() // t = ()\n```\n\n### Simple Macro Processing\n\n```csharp\n#define DEBUG\n\n// only support two below format:\n//    1. #ifdef xxx { body }\n//    2. #ifdef xxx { body } #else { body }, here only one '#else' is supported'.\n#ifdef DEBUG2\n{\n    add = fn(x, y) { x + y }\n    printf(\"add = %d\\n\", add(1, 2))\n}\n#else\n{\n    sub = fn(x, y) { x - y }\n    printf(\"sub = %d\\n\", sub(3, 1))\n}\n\n#define TESTING\n#ifdef TESTING\n{\n    add = fn(x, y) { x + y }\n    printf(\"add = %d\\n\", add(1, 2))\n}\n```\n\n### Function\n\n* Default value\n* Variadic parameters\n* Mutiple return values\n\n```csharp\n//Function with default values and variadic parameters\nadd = fn(x, y=5, z=7, args...) {\n    w = x + y + z\n    for i in args {\n        w += i\n    }\n    return w\n}\nw = add(2,3,4,5,6,7)\nprintln(w)\n\nlet z = (x,y) =\u003e x * y + 5\nprintln(z(3,4)) //result :17\n\n# multiple returns\nfn testReturn(a, b, c, d=40) {\n    return a, b, c, d\n}\nlet (x, y, c, d) = testReturn(10, 20, 30) // d is 40\n```\n\n### Command Execution\n\nYou could use backtick for command execution(like Perl).\n\n```csharp\nif (RUNTIME_OS == \"linux\") {\n    var = \"~\"\n    out = `ls -la $var`\n    println(out)\n}\nelif (RUNTIME_OS == \"windows\") {\n    out = `dir`\n    println(out)\n\n    println(\"\")\n    println(\"\")\n    //test command not exists\n    out = `dirs`\n    if (!out.ok) {\n        printf(\"Error: %s\\n\", out)\n    }\n}\n```\n\n### async/await processing\nVM support `async/await`.\n\n```csharp\nlet add = async fn(a, b) { a + b }\n\nresult = await add(3, 4)\nprintln(result)\n```\n\n### Class\n\n* Simple\n* Inheritance\n* Operator overloading\n* Property(like c#)\n* Indexer\n\n#### Simple\n\n```csharp\nclass Animal {\n    let name = \"\"\n    fn init(name) {    //'init' is the constructor\n        //do somthing\n    }\n}\n```\n\n#### Inheritance\n\n```csharp\nclass Dog : Animal { //Dog inherits from Animal\n}\n```\n\n#### Operator overloading\n\n```csharp\nclass Vector {\n    let x = 0;\n    let y = 0;\n\n    fn init (a, b) {\n        x = a; y = b\n    }\n\n    fn +(v) { //overloading '+'\n        if (type(v) == \"INTEGER\" {\n            return new Vector(x + v, y + v);\n        } elif v.is_a(Vector) {\n            return new Vector(x + v.x, y + v.y);\n        }\n        return nil;\n    }\n\n    fn String() {\n        return fmt.sprintf(\"(%v),(%v)\", this.x, this.y);\n    }\n}\nv1 = new Vector(1,2);\nv2 = new Vector(4,5);\n\nv3 = v1 + v2\nprintln(v3.String());\n\nv4 = v1 + 10\nprintln(v4.String());\n```\n\n#### Property(like c#)\n\n```csharp\nclass Date {\n    let month = 7;  // Backing store\n    property Month\n    {\n        get { return month }\n        set {\n            if ((value \u003e 0) \u0026\u0026 (value \u003c 13))\n            {\n                month = value\n            } else {\n               println(\"BAD, month is invalid\")\n            }\n        }\n    }\n\n    property Year; // same as 'property Year { get; set;}'\n    property Day { get; }\n\n    fn init(year, month, day) {\n        this.Year = year\n        this.Month = month\n        this.Day = day\n    }\n\n    fn getDateInfo() {\n        printf(\"Year:%v, Month:%v, Day:%v\\n\", this.Year, this.Month, this.Day)\n    }\n}\n\ndateObj = new Date(2000, 5, 11)\ndateObj.getDateInfo()\n```\n\n#### Indexer\n\n```csharp\nclass IndexedNames\n{\n    let namelist = []\n    let size = 10\n    fn init()\n    {\n        let i = 0\n        for (i = 0; i \u003c size; i++)\n        {\n            namelist[i] = \"N. A.\"\n        }\n    }\n\n    fn getNameList() {\n        println(namelist)\n    }\n\n    property this[index] //index must be property\n    {\n        get\n        {\n            let tmp;\n            if ( index \u003e= 0 \u0026\u0026 index \u003c= size - 1 )\n            {\n               tmp = namelist[index]\n            }\n            else\n            {\n               tmp = \"\"\n            }\n            return tmp\n         }\n         set\n         {\n             if ( index \u003e= 0 \u0026\u0026 index \u003c= size-1 )\n             {\n                 namelist[index] = value\n             }\n         }\n    }\n}\nnamesObj = new IndexedNames()\n\n//Below code will call Indexer's setter function\nnamesObj[0] = \"Zara\"\nnamesObj[1] = \"Riz\"\nnamesObj[2] = \"Nuha\"\nnamesObj[3] = \"Asif\"\nnamesObj[4] = \"Davinder\"\nnamesObj[5] = \"Sunil\"\nnamesObj[6] = \"Rubic\"\n\nnamesObj.getNameList()\nfor (i = 0; i \u003c namesObj.size; i++)\n{\n    println(namesObj[i]) //Calling Indexer's getter function\n}\n```\n\n### Standard input/output/error\n\nThere are three predefined object for representing standard input, standard output, standard error.\nThey are `stdin`, `stdout`, `stderr`.\n\n```csharp\nstdout.writeLine(\"Hello world\")\n//same as above\nfmt.fprintf(stdout, \"Hello world\\n\")\n\nprint(\"Please type your name:\")\nname = stdin.read(1024)  //read up to 1024 bytes from stdin\nprintln(\"Your name is \" + name)\n\n//You can also using Insertion operator (`\u003c\u003c`) and Extraction operator(`\u003e\u003e`)\n//just like c++ to operate stdin/stdout/stderr.\nstdout \u003c\u003c \"hello \" \u003c\u003c \"world!\" \u003c\u003c \" How are you?\" \u003c\u003c endl;\n```\n\n### Exception Handling(try-catch-finally)\n\n```csharp\n// Note: Only support throw string type\nlet exceptStr = \"SUMERROR\"\ntry {\n    let th = 1 + 2\n    if (th == 3) { throw exceptStr }\n}\ncatch \"OTHERERROR\" {\n    println(\"Catched OTHERERROR\")\n}\ncatch exceptStr {\n    println(\"Catched is SUMERROR\")\n}\ncatch {\n    println(\"Catched ALL\")\n}\nfinally {\n    println(\"finally running\")\n}\n```\n\n### Optional Type(Java 8 like)\n\n```csharp\nfn safeDivision?(a, b) {\n    if (b == 0){\n        return optional.empty();\n    } else {\n        return optional.of(a/b);\n    }\n}\n\nop1 = safeDivision?(10, 0)\nif (!op1.isPresent()) {\n    println(op1)\n}\n```\n\n### Regular expression\n\n```csharp\n//literal: /pattern/.match(str)\nlet regex = /\\d+\\t/.match(\"abc 123 mnj\")\nif (regex) {\n    println(\"regex matched using regular expression literal\")\n}\n\n//Use '=~'(str =~ pattern)\nif \"abc 123\tmnj\" =~ ``\\d+\\t`` {\n    println(\"regex matched using '=~'\")\n}else {\n    println(\"regex not matched using '=~'\")\n}\n```\n\n### Pipe Operator\n\n```csharp\n// Test pipe operator(|\u003e)\nx = [\"hello\", \"world\"] |\u003e strings.join(\" \") |\u003e strings.upper() |\u003e strings.lower() |\u003e strings.title()\n\n//same as above\n//x = [\"hello\", \"world\"] |\u003e strings.join(\" \") |\u003e strings.upper |\u003e strings.lower |\u003e strings.title\nprintf(\"x=\u003c%s\u003e\\n\", x)\n```\n\n### linq\n\n```csharp\nlet mm = [1,2,3,4,5,6,7,8,9,10]\nresult = linq.from(mm).where(x =\u003e x % 2 == 0).select(x =\u003e x + 2).toSlice()\n\nprintln('before mm={mm}')\nprintln('after result={result}')\n```\n\n### json module(for json marshal \u0026 unmarshal)\n\n```csharp\nlet hsJson = {\"key1\" : 10,\n              \"key2\" : \"Hello Json %s %s Module\",\n              \"key3\" : 15.8912,\n              \"key4\" : [1,2,3.5, \"Hello\"],\n              \"key5\" : true,\n              \"key6\" : {\"subkey1\": 12, \"subkey2\": \"Json\"},\n              \"key7\" : fn(x,y){x+y}(1,2)\n}\nlet hashStr = json.marshal(hsJson) //same as 'json.toJson(hsJson)'\nprintln(json.indent(hashStr, \"  \"))\n\nlet hsJson1 = json.unmarshal(hashStr)\nprintln(hsJson1)\n\n\nlet arrJson = [1,2.3,\"HHF\",[],{ \"key\" : 10, \"key1\" : 11}]\nlet arrStr = json.marshal(arrJson)\nprintln(json.indent(arrStr))\nlet arr1Json = json.unmarshal(arrStr)  //same as 'json.fromJson(arrStr)'\nprintln(arr1Json)\n```\n\n### User Defined Operator\n\n```csharp\n//infix operator '=@' which accept two parameters.\nfn =@(x, y) {\n    return x + y * y\n}\nlet pp = 10 =@ 5 // Use the '=@' user defined infix operator\nprintf(\"pp=%d\\n\", pp) // result: pp=35\n\n\n//prefix operator '=^' which accept only one parameter.\nfn =^(x) {\n    return -x\n}\nlet hh = =^10 // Use the '=^' prefix operator\nprintf(\"hh=%d\\n\", hh) // result: hh=-10\n```\n\n### using statement(C# like)\n\n```csharp\n// No need for calling infile.close().\nusing (infile = newFile(\"./file.demo\", \"r\")) {\n    if (infile == nil) {\n        println(\"opening 'file.demo' for reading failed, error:\", infile.message())\n        os.exit(1)\n    }\n\n    let line;\n    let num = 0\n    //Read file by using extraction operator(\"\u003e\u003e\")\n    while (infile\u003e\u003eline != nil) {\n        num++\n        printf(\"%d %s\\n\", num, line)\n    }\n}\n```\n\n## Contributing\n\nContributing is very welcomed. If you make any changes to the language, please let me know,\nso i could put you in the `Credits` sections.\n\n## Credits\n\n* mayoms:\n    This project is based on mayoms's [monkey](https://github.com/mayoms/monkey) interpreter.\n\n* ahmetb：\n    Linq module is base on ahmetb's [linq](https://github.com/ahmetb/go-linq)\n\n* shopspring：\n   Decimal module is based on shopspring's [decimal](https://github.com/shopspring/decimal)\n\n* gorilla:\n   Service module is based on gorilla's [mux](https://github.com/gorilla/mux)\n\n## Installation\n\nJust download the repository and run `./run.sh`\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fx-research-team%2Fvm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fx-research-team%2Fvm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fx-research-team%2Fvm/lists"}