diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..3c26f7f --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,32 @@ +name: Go + +on: + push: + tags: + - "*" + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: 1.21 + id: go + + - name: Test + run: go mod tidy && make test + + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v5 + with: + distribution: goreleaser + version: latest + args: release --clean + env: + GITHUB_TOKEN: ${{ secrets.GO_RELEASER_GITHUB_TOKEN }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index fa3aa02..7f6c282 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -14,7 +14,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.21 - name: Test run: go mod tidy && make test diff --git a/.gitignore b/.gitignore index 2631fb3..2443257 100644 --- a/.gitignore +++ b/.gitignore @@ -52,7 +52,10 @@ nuru Notes.md tutorials/en/* config.json +*local* # For Nuru executables /nuru /Nuru + +dist/ diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000..92e6585 --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,47 @@ +project_name: nuru +before: + hooks: + - go mod tidy + - go generate ./... + +builds: + - env: + - CGO_ENABLED=0 + goos: + - linux + - windows + - darwin + - android + ldflags: + - "-s -w" + ignore: + - goos: android + goarch: 386 + +archives: + - format: tar.gz + name_template: >- + nuru_ + {{- title .Os }}_ + {{- if eq .Arch "amd64" }}amd64 + {{- else if eq .Arch "386" }}i386 + {{- else }}{{ .Arch }}{{ end }} + {{- if .Arm }}v{{ .Arm }}{{ end }} + format_overrides: + - goos: windows + format: zip + +changelog: + sort: asc + filters: + exclude: + - "^docs:" + - "^test:" + +nfpms: + - maintainer: "AvicennaJr" + homepage: "https://nuruprogramming.org" + description: "Nuru is a programming language built from the ground up" + formats: + - deb + file_name_template: "{{ .ProjectName }}.{{ .Os }}-{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" diff --git a/Makefile b/Makefile index 0df4787..eec06e6 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION=0.5.0-alpha +VERSION=0.5.1 build_linux: @echo 'building linux binary...' diff --git a/README.md b/README.md index 64b61c1..276c936 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@

NURUπŸ”₯PROGRAMMINGπŸ”₯LANGUAGE

- Nuru Programming Language - Nuru Programming Language - Nuru Programming Language + Nuru Programming Language + Nuru Programming Language + Nuru Programming Language
- Nuru Programming Language - Nuru Programming Language - Nuru Programming Language + Nuru Programming Language + Nuru Programming Language + Nuru Programming Language
- Nuru Programming Language + Nuru Programming Language

A Swahili Programming Language of its kind built from the ground up. @@ -18,89 +18,136 @@ To get started download the executables from the release page or follow the inst ### Linux - - Download the binary: +- Download the binary: ``` -curl -O -L https://github.com/AvicennaJr/Nuru/releases/download/v0.5.0-alpha/nuru_linux_amd64_v0.5.0-alpha.tar.gz +curl -O -L https://github.com/NuruProgramming/Nuru/releases/download/v0.5.18/nuru_Linux_amd64.tar.gz ``` - - Extract the file to make global available: +- Extract the file to make global available: ``` -sudo tar -C /usr/local/bin -xzvf nuru_linux_amd64_v0.5.0-alpha.tar.gz +sudo tar -C /usr/local/bin -xzvf nuru_Linux_amd64.tar.gz ``` - - Confirm installation with: +- Confirm installation with: ``` nuru -v ``` - ### MacOs ( Apple silicon Mac ) - - Download the binary: +- Download the binary: -``` -curl -O -L https://github.com/AvicennaJr/Nuru/releases/download/v0.5.0-alpha/nuru_mac_arm64_v0.5.0-alpha.tar.gz -``` + - For apple silicon mac use: - - Extract the file to make global available: + ``` + curl -O -L https://github.com/NuruProgramming/Nuru/releases/download/v0.5.18/nuru_Darwin_arm64.tar.gz + ``` -``` -sudo tar -C /usr/local/bin -xzvf nuru_mac_arm64_v0.5.0-alpha.tar.gz -``` + - For apple intel mac use: + + ``` + curl -O -L https://github.com/NuruProgramming/Nuru/releases/download/v0.5.18/nuru_Darwin_amd64.tar.gz + ``` + +- Extract the file to make global available: - - Confirm installation with: + - For apple silicon mac use: + + ``` + sudo tar -C /usr/local/bin -xzvf nuru_Darwin_arm64.tar.gz + ``` + + - For apple intel mac use: + + ``` + sudo tar -C /usr/local/bin -xzvf nuru_Darwin_amd64.tar.gz + ``` + +- Confirm installation with: ``` nuru -v ``` - ### Android (Termux) - - Make sure you have [Termux](https://f-droid.org/repo/com.termux_118.apk) installed. - - Download the binary with this command: +To install Nuru on your Android device using Termux, follow these steps: -``` -curl -O -L https://github.com/AvicennaJr/Nuru/releases/download/v0.5.0-alpha/nuru_android_arm64_v0.5.0-alpha.tar.gz -``` - - Extract the file: +1. **Ensure Termux is installed**: -``` -tar -xzvf nuru_android_arm64_v0.5.0-alpha.tar.gz -``` - - Add it to path: + - You can download and install [Termux](https://f-droid.org/en/packages/com.termux/). -``` -echo "alias nuru='~/nuru'" >> .bashrc -``` - - Confirm installation with: +2. **Create the target directory**: -``` -nuru -v + ```bash + mkdir -p /data/data/com.termux/files/usr/share/nuru + ``` + +3. **Download the Nuru package**: + + ```bash + curl -O -L https://github.com/NuruProgramming/Nuru/releases/download/v0.5.18/nuru_Android_arm64.tar.gz + ``` + +4. **Extract the files to the target directory**: + + ```bash + tar -xzvf nuru_Android_arm64.tar.gz -C /data/data/com.termux/files/usr/share/nuru + ``` + +5. **Set up an alias for easy access**: + + ```bash + echo "alias nuru='/data/data/com.termux/files/usr/share/nuru/nuru'" >> ~/.bashrc + ``` + +6. **Reload the .bashrc file to apply the alias**: + + ```bash + source ~/.bashrc + ``` + +7. **Verify the installation**: + ```bash + nuru -v + ``` + +For a more streamlined installation, you can use the following one-liner: + +```bash +curl -O -L https://github.com/NuruProgramming/Nuru/releases/download/v0.5.18/nuru_Android_arm64.tar.gz && mkdir -p /data/data/com.termux/files/usr/share/nuru && tar -xzvf nuru_Android_arm64.tar.gz -C /data/data/com.termux/files/usr/share/nuru && echo "alias nuru='/data/data/com.termux/files/usr/share/nuru/nuru'" >> ~/.bashrc && source ~/.bashrc && echo "Installation complete.." ``` ### Windows - Executable: - - Download the Nuru executable [Here](https://github.com/AvicennaJr/Nuru/releases/download/v0.5.0-alpha/nuru_windows_amd64_v0.5.0-alpha.exe) - - Double click the executable + + - Download the Nuru zip file [Here](https://github.com/NuruProgramming/Nuru/releases/download/v0.5.18/nuru_Windows_amd64.zip) + - Unzip to get the executable + - Double click the executable - Nuru Installer - > Coming Soon + > Coming Soon ### Building From Source - - Make sure you have golang installed (atleast 1.19.0 and above) - - Run the following command: +- Make sure you have golang installed (atleast 1.19.0 and above) +- Run the following command: ``` -go build -o nuru main.go +go build -o nuru . ``` - - You can optionally add the binary to $PATH as shown above - - Confirm installtion with: + +- Copy nuru binary to path destination ~/go/bin + +``` +cp nuru ~/go/bin +``` + +- Confirm installtion with: ``` nuru -v @@ -109,7 +156,8 @@ nuru -v ## Syntax At A Glance **NOTE** -> There is a more detailed documentation of the language [here](./repl/docs/en/README.md). + +> There is a more detailed documentation of the language [here](https://nuruprogramming.org). Nuru, although still in its early stage, intends to be a fully functional programming language, and thus it has been baked with many features. @@ -123,10 +171,13 @@ y = 3; andika(x*y) // output is 6 ``` + You can also use the `fanya` keyword to define a variabe: + ``` fanya x = 3 ``` + **Note that `fanya` keyword is OPTIONAL** ### Comments @@ -139,8 +190,8 @@ Nuru supports both single line and multiple line comments as shown below: /* Multiple Line -Comment -*/ +Comment +*/ ``` ### Arithmetic Operations @@ -157,15 +208,15 @@ For now Nuru supports `+`, `-`, `/`, `*` and `%`. Nuru also provides precedence Nuru has the following types: -Type | Syntax | Comments ---------- | ----------------------------------------- | ----------------------- -BOOL | `kweli sikweli` | kweli == true, sikweli == false -INT | `1, 100, 342, -4` | These are signed 64 bit integers -FLOAT | `2.3, 4.5. 100.8094` | Signed 64 bit floats -STRING | `"" "mambo" "habari yako"` | They can be in double `"` or single `'` quotes -ARRAY | `[] [1, 2, 3] [1, "moja", kweli]` | Arrays can hold any types -DICT | `{} {"a": 3, 1: "moja", kweli: 2}` | Keys can be int, string or bool. Values can be anything -NULL | `tupu` | These are nil objects +| Type | Syntax | Comments | +| ------ | ---------------------------------- | ------------------------------------------------------- | +| BOOL | `kweli sikweli` | kweli == true, sikweli == false | +| INT | `1, 100, 342, -4` | These are signed 64 bit integers | +| FLOAT | `2.3, 4.5. 100.8094` | Signed 64 bit floats | +| STRING | `"" "mambo" "habari yako"` | They can be in double `"` or single `'` quotes | +| ARRAY | `[] [1, 2, 3] [1, "moja", kweli]` | Arrays can hold any types | +| DICT | `{} {"a": 3, 1: "moja", kweli: 2}` | Keys can be int, string or bool. Values can be anything | +| NULL | `tupu` | These are nil objects | ### Functions @@ -223,6 +274,7 @@ wakati (i > 0) { ### Arrays This is how you initiliaze and perform other array operations in Nuru: + ``` arr = [] @@ -252,10 +304,11 @@ andika(arr[3]) // output = 3 ### Dictionaries Nuru also supports dictionaries and you can do a lot with them as follows: + ``` mtu = {"jina": "Mojo", "kabila": "Mnyakusa"} -// get value from key +// get value from key andika(mtu["jina"]) // output = Mojo andika(mtu["kabila"]); // output = Mnyakusa @@ -284,6 +337,7 @@ andika(mtu) // output = {"jina": "Avicenna", "kabila": "Mnyakusa", "anapoishi": ### For Loops These can iterate over strings, arrays and dictionaries: + ``` kwa i ktk "habari" { andika(i) @@ -301,6 +355,7 @@ i ### Getting Input From User In Nuru you can get input from users using the `jaza()` keyword as follows: + ``` jina = jaza("Unaitwa nani? ") // will prompt for input @@ -312,6 +367,7 @@ andika("Habari yako " + jina) ### Using The Intepreter: You can enter the intepreter by simply running the `nuru` command: + ``` nuru >>> andika("karibu") @@ -319,10 +375,13 @@ karibu >>> 2 + 2 4 ``` + Kindly Note that everything should be placed in a single line. Here's an example: + ``` >>> kama (x > y) {andika("X ni kubwa")} sivyo {andika("Y ni kubwa")} ``` + ### Running From File To run a Nuru script, write the `nuru` command followed by the name of the file with a `.nr` or `.sw` extension: @@ -333,7 +392,7 @@ nuru myFile.nr ## Issues -Kindly open an [Issue](https://github.com/AvicennaJr/Nuru/issues) to make suggestions and anything else. +Kindly open an [Issue](https://github.com/NuruProgramming/Nuru/issues) to make suggestions and anything else. ## Contributions @@ -345,6 +404,8 @@ There are documentations for two languages, English and Kiswahili, which are bot Clone the repo, hack it, make sure all tests are passing then submit a pull request. +> Make sure ALL tests are passing before making a pull request. You can confirm with running `make tests` + ## Community Nuru has a passionate community, join us on [Telegram](https://t.me/NuruProgrammingChat) diff --git a/ast/ast.go b/ast/ast.go index bc15253..c42241f 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -4,12 +4,12 @@ import ( "bytes" "strings" - "github.com/AvicennaJr/Nuru/token" + "github.com/NuruProgramming/Nuru/token" ) type Node interface { TokenLiteral() string - String() string // to help debug the many errors lmao + String() string } type Statement interface { diff --git a/ast/ast_test.go b/ast/ast_test.go index c5ae5fa..f9eba0d 100644 --- a/ast/ast_test.go +++ b/ast/ast_test.go @@ -3,7 +3,7 @@ package ast import ( "testing" - "github.com/AvicennaJr/Nuru/token" + "github.com/NuruProgramming/Nuru/token" ) func TestString(t *testing.T) { diff --git a/evaluator/assign.go b/evaluator/assign.go index b78d931..f867321 100644 --- a/evaluator/assign.go +++ b/evaluator/assign.go @@ -1,8 +1,8 @@ package evaluator import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/object" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/object" ) func evalAssign(node *ast.Assign, env *object.Environment) object.Object { diff --git a/evaluator/assignEqual.go b/evaluator/assignEqual.go index 551ecd9..6ec2bf2 100644 --- a/evaluator/assignEqual.go +++ b/evaluator/assignEqual.go @@ -3,8 +3,8 @@ package evaluator import ( "strings" - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/object" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/object" ) func evalAssignEqual(node *ast.AssignEqual, env *object.Environment) object.Object { diff --git a/evaluator/at.go b/evaluator/at.go index f1b5558..6cdb35f 100644 --- a/evaluator/at.go +++ b/evaluator/at.go @@ -1,8 +1,8 @@ package evaluator import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/object" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/object" ) func evalAt(node *ast.At, env *object.Environment) object.Object { diff --git a/evaluator/bang.go b/evaluator/bang.go index de9b340..ee7d6fb 100644 --- a/evaluator/bang.go +++ b/evaluator/bang.go @@ -1,6 +1,6 @@ package evaluator -import "github.com/AvicennaJr/Nuru/object" +import "github.com/NuruProgramming/Nuru/object" func evalBangOperatorExpression(right object.Object) object.Object { switch right { @@ -13,4 +13,4 @@ func evalBangOperatorExpression(right object.Object) object.Object { default: return FALSE } -} \ No newline at end of file +} diff --git a/evaluator/block.go b/evaluator/block.go index ba1286a..3e27ef5 100644 --- a/evaluator/block.go +++ b/evaluator/block.go @@ -1,8 +1,8 @@ package evaluator import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/object" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/object" ) func evalBlockStatement(block *ast.BlockStatement, env *object.Environment) object.Object { diff --git a/evaluator/builtins.go b/evaluator/builtins.go index 806689d..d35f1e9 100644 --- a/evaluator/builtins.go +++ b/evaluator/builtins.go @@ -7,7 +7,7 @@ import ( "os" "strings" - "github.com/AvicennaJr/Nuru/object" + "github.com/NuruProgramming/Nuru/object" ) var builtins = map[string]*object.Builtin{ @@ -74,7 +74,7 @@ var builtins = map[string]*object.Builtin{ "aina": { Fn: func(args ...object.Object) object.Object { if len(args) != 1 { - return newError("Samahani, tunahitaji Hoja 1, wewe umeweka %d", len(args)) + return newError("Samahani, tunahitaji hoja 1, wewe umeweka %d", len(args)) } return &object.String{Value: string(args[0].Type())} @@ -90,11 +90,111 @@ var builtins = map[string]*object.Builtin{ file, err := os.ReadFile(filename) if err != nil { - return &object.Error{Message: "Tumeshindwa kusoma faili"} + return &object.Error{Message: "Tumeshindwa kusoma faili au faili halipo"} } return &object.File{Filename: filename, Content: string(file)} }, }, + "mfululizo": { + Fn: func(args ...object.Object) object.Object { + if len(args) < 1 || len(args) > 3 { + return newError("Samahani, mfululizo inahitaji hoja 1 hadi 3, wewe umeweka %d", len(args)) + } + + var start, end, step int64 + var err error + + switch len(args) { + case 1: + end, err = getIntValue(args[0]) + if err != nil { + return newError("Hoja lazima iwe nambari nzima") + } + start, step = 0, 1 + case 2: + start, err = getIntValue(args[0]) + if err != nil { + return newError("Hoja ya kwanza lazima iwe nambari nzima") + } + end, err = getIntValue(args[1]) + if err != nil { + return newError("Hoja ya pili lazima iwe nambari nzima") + } + step = 1 + case 3: + start, err = getIntValue(args[0]) + if err != nil { + return newError("Hoja ya kwanza lazima iwe nambari nzima") + } + end, err = getIntValue(args[1]) + if err != nil { + return newError("Hoja ya pili lazima iwe nambari nzima") + } + step, err = getIntValue(args[2]) + if err != nil { + return newError("Hoja ya tatu lazima iwe nambari nzima") + } + if step == 0 { + return newError("Hatua haiwezi kuwa sifuri") + } + } + + elements := []object.Object{} + for i := start; (step > 0 && i < end) || (step < 0 && i > end); i += step { + elements = append(elements, &object.Integer{Value: i}) + } + + return &object.Array{Elements: elements} + }, + }, + + "badilisha": { + Fn: func(args ...object.Object) object.Object { + if len(args) != 2 { + return newError("Samahani, badili inahitaji hoja 2, wewe umeweka %d", len(args)) + } + + value := args[0] + targetType := args[1] + + if targetType.Type() != object.STRING_OBJ { + return newError("Aina ya lengo lazima iwe neno") + } + + targetTypeStr := targetType.(*object.String).Value + + switch targetTypeStr { + case "NAMBA": + return convertToInteger(value) + case "DESIMALI": + return convertToFloat(value) + case "NENO": + return convertToString(value) + case "BOOLEAN": + return convertToBoolean(value) + default: + return newError("Aina isiyojulikana: %s", targetTypeStr) + } + }, + }, + "namba": { + Fn: func(args ...object.Object) object.Object { + if len(args) != 1 { + return newError("Samahani, namba inahitaji hoja 1, wewe umeweka %d", len(args)) + } + value := args[0] + return convertToInteger(value) + }, + }, + "tungo": { + Fn: func(args ...object.Object) object.Object { + if len(args) != 1 { + return newError("Samahani, tungo inahitaji hoja 1, wewe umeweka %d", len(args)) + } + value := args[0] + return convertToString(value) + }, + }, // "jumla": { // Fn: func(args ...object.Object) object.Object { @@ -135,3 +235,12 @@ var builtins = map[string]*object.Builtin{ // }, // }, } + +func getIntValue(obj object.Object) (int64, error) { + switch obj := obj.(type) { + case *object.Integer: + return obj.Value, nil + default: + return 0, fmt.Errorf("expected integer, got %T", obj) + } +} diff --git a/evaluator/call.go b/evaluator/call.go index 4b75811..b936afe 100644 --- a/evaluator/call.go +++ b/evaluator/call.go @@ -1,8 +1,8 @@ package evaluator import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/object" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/object" ) func evalCall(node *ast.CallExpression, env *object.Environment) object.Object { diff --git a/evaluator/dict.go b/evaluator/dict.go index 05bbdcb..2d417ca 100644 --- a/evaluator/dict.go +++ b/evaluator/dict.go @@ -1,8 +1,8 @@ package evaluator import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/object" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/object" ) func evalDictLiteral(node *ast.DictLiteral, env *object.Environment) object.Object { @@ -29,4 +29,4 @@ func evalDictLiteral(node *ast.DictLiteral, env *object.Environment) object.Obje } return &object.Dict{Pairs: pairs} -} \ No newline at end of file +} diff --git a/evaluator/evaluator.go b/evaluator/evaluator.go index 70f2db9..5fd219d 100644 --- a/evaluator/evaluator.go +++ b/evaluator/evaluator.go @@ -3,8 +3,8 @@ package evaluator import ( "fmt" - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/object" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/object" ) var ( @@ -45,7 +45,7 @@ func Eval(node ast.Node, env *object.Environment) object.Object { return left } right := Eval(node.Right, env) - if isError(right) { + if isError(right) && right != nil { return right } return evalInfixExpression(node.Operator, left, right, node.Token.Line) @@ -134,7 +134,7 @@ func Eval(node ast.Node, env *object.Environment) object.Object { return val } return evalPropertyAssignment(node.Name, val, env) - case *ast.Assign: // making let temporarily optional as I debug + case *ast.Assign: return evalAssign(node, env) case *ast.AssignEqual: return evalAssignEqual(node, env) @@ -180,7 +180,7 @@ func Eval(node ast.Node, env *object.Environment) object.Object { } array.Elements[idx.Value] = value } else { - return newError("Hauwezi kufanya opereshen hii na %#v", index) + return newError("Hauwezi kufanya operesheni hii na %#v", index) } } else if hash, ok := obj.(*object.Dict); ok { key := Eval(ie.Index, env) @@ -191,13 +191,13 @@ func Eval(node ast.Node, env *object.Environment) object.Object { hashed := hashKey.HashKey() hash.Pairs[hashed] = object.DictPair{Key: key, Value: value} } else { - return newError("Hauwezi kufanya opereshen hii na %T", key) + return newError("Hauwezi kufanya operesheni hii na %T", key) } } else { - return newError("%T haifanyi operation hii", obj) + return newError("%T haifanyi operesheni hii", obj) } } else { - return newError("Tumia neno kama variable, sio %T", left) + return newError("Tumia neno kama kibadala, sio %T", left) } } diff --git a/evaluator/evaluator_test.go b/evaluator/evaluator_test.go index 0e72748..b6e830d 100644 --- a/evaluator/evaluator_test.go +++ b/evaluator/evaluator_test.go @@ -5,9 +5,9 @@ import ( "testing" "time" - "github.com/AvicennaJr/Nuru/lexer" - "github.com/AvicennaJr/Nuru/object" - "github.com/AvicennaJr/Nuru/parser" + "github.com/NuruProgramming/Nuru/lexer" + "github.com/NuruProgramming/Nuru/object" + "github.com/NuruProgramming/Nuru/parser" ) func TestEvalIntegerExpression(t *testing.T) { @@ -22,7 +22,6 @@ func TestEvalIntegerExpression(t *testing.T) { {"5 + 5 + 5 + 5 - 10", 10}, {"2 * 2 * 2 * 2", 16}, {"2 / 2 + 1", 2}, - {"2**3", 8}, } for _, tt := range tests { @@ -31,6 +30,20 @@ func TestEvalIntegerExpression(t *testing.T) { } } +func TestEvalFloatExpression(t *testing.T) { + tests := []struct { + input string + expected float64 + }{ + {"2**3", 8.0}, + } + + for _, tt := range tests { + evaluated := testEval(tt.input) + testFloatObject(t, evaluated, tt.expected) + } +} + func TestEvalBooleanExpression(t *testing.T) { tests := []struct { input string @@ -206,27 +219,27 @@ func TestErrorHandling(t *testing.T) { }{ { "5 + kweli", - "Mstari 0: Aina Hazilingani: NAMBA + BOOLEAN", + "Mstari 1: Aina Hazilingani: NAMBA + BOOLEAN", }, { "5 + kweli; 5;", - "Mstari 0: Aina Hazilingani: NAMBA + BOOLEAN", + "Mstari 1: Aina Hazilingani: NAMBA + BOOLEAN", }, { "-kweli", - "Mstari 0: Operesheni Haielweki: -BOOLEAN", + "Mstari 1: Operesheni Haieleweki: -BOOLEAN", }, { "kweli + sikweli", - "Mstari 0: Operesheni Haielweki: BOOLEAN + BOOLEAN", + "Mstari 1: Operesheni Haieleweki: BOOLEAN + BOOLEAN", }, { "5; kweli + sikweli; 5", - "Mstari 0: Operesheni Haielweki: BOOLEAN + BOOLEAN", + "Mstari 1: Operesheni Haieleweki: BOOLEAN + BOOLEAN", }, { "kama (10 > 1) { kweli + sikweli;}", - "Mstari 0: Operesheni Haielweki: BOOLEAN + BOOLEAN", + "Mstari 1: Operesheni Haieleweki: BOOLEAN + BOOLEAN", }, { ` @@ -238,19 +251,19 @@ kama (10 > 1) { rudisha 1; } `, - "Mstari 3: Operesheni Haielweki: BOOLEAN + BOOLEAN", + "Mstari 4: Operesheni Haieleweki: BOOLEAN + BOOLEAN", }, { "bangi", - "Mstari 0: Neno Halifahamiki: bangi", + "Mstari 1: Neno Halifahamiki: bangi", }, { `"Habari" - "Habari"`, - "Mstari 0: Operesheni Haielweki: NENO - NENO", + "Mstari 1: Operesheni Haieleweki: NENO - NENO", }, { `{"jina": "Avi"}[unda(x) {x}];`, - "Mstari 0: Samahani, UNDO (FUNCTION) haitumiki kama key", + "Mstari 1: Samahani, UNDO (FUNCTION) haitumiki kama ufunguo", }, } diff --git a/evaluator/forin.go b/evaluator/forin.go index 28db0f5..f5db434 100644 --- a/evaluator/forin.go +++ b/evaluator/forin.go @@ -1,8 +1,8 @@ package evaluator import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/object" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/object" ) func evalForInExpression(fie *ast.ForIn, env *object.Environment, line int) object.Object { @@ -26,4 +26,4 @@ func evalForInExpression(fie *ast.ForIn, env *object.Environment, line int) obje default: return newError("Mstari %d: Huwezi kufanya operesheni hii na %s", line, i.Type()) } -} \ No newline at end of file +} diff --git a/evaluator/function.go b/evaluator/function.go index aa413d5..9e9605d 100644 --- a/evaluator/function.go +++ b/evaluator/function.go @@ -1,8 +1,8 @@ package evaluator import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/object" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/object" ) func evalFunction(node *ast.FunctionLiteral, env *object.Environment) object.Object { diff --git a/evaluator/identifier.go b/evaluator/identifier.go index 7745a23..49f8272 100644 --- a/evaluator/identifier.go +++ b/evaluator/identifier.go @@ -1,8 +1,8 @@ package evaluator import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/object" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/object" ) func evalIdentifier(node *ast.Identifier, env *object.Environment) object.Object { @@ -14,4 +14,4 @@ func evalIdentifier(node *ast.Identifier, env *object.Environment) object.Object } return newError("Mstari %d: Neno Halifahamiki: %s", node.Token.Line, node.Value) -} \ No newline at end of file +} diff --git a/evaluator/if.go b/evaluator/if.go index 890f24f..8a11e81 100644 --- a/evaluator/if.go +++ b/evaluator/if.go @@ -1,8 +1,8 @@ package evaluator import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/object" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/object" ) func evalIfExpression(ie *ast.IfExpression, env *object.Environment) object.Object { @@ -19,4 +19,4 @@ func evalIfExpression(ie *ast.IfExpression, env *object.Environment) object.Obje } else { return NULL } -} \ No newline at end of file +} diff --git a/evaluator/import.go b/evaluator/import.go index 0375a3c..8b5eb23 100644 --- a/evaluator/import.go +++ b/evaluator/import.go @@ -2,16 +2,15 @@ package evaluator import ( "fmt" - "io/ioutil" "os" "path/filepath" "strings" - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/lexer" - "github.com/AvicennaJr/Nuru/module" - "github.com/AvicennaJr/Nuru/object" - "github.com/AvicennaJr/Nuru/parser" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/lexer" + "github.com/NuruProgramming/Nuru/module" + "github.com/NuruProgramming/Nuru/object" + "github.com/NuruProgramming/Nuru/parser" ) var searchPaths []string @@ -31,7 +30,7 @@ func evalImportFile(name string, ident *ast.Identifier, env *object.Environment) addSearchPath("") filename := findFile(name) if filename == "" { - return newError("Module %s haipo", name) + return newError("Moduli %s haipo", name) } var scope *object.Environment scope, err := evaluateFile(filename, env) @@ -62,7 +61,7 @@ func fileExists(file string) bool { } func evaluateFile(file string, env *object.Environment) (*object.Environment, object.Object) { - source, err := ioutil.ReadFile(file) + source, err := os.ReadFile(file) if err != nil { return nil, &object.Error{Message: fmt.Sprintf("Tumeshindwa kufungua pakeji: %s", file)} } @@ -70,7 +69,7 @@ func evaluateFile(file string, env *object.Environment) (*object.Environment, ob p := parser.New(l) program := p.ParseProgram() if len(p.Errors()) != 0 { - return nil, &object.Error{Message: fmt.Sprintf("Pakeji %s ina errors zifuatozo:\n%s", file, strings.Join(p.Errors(), "\n"))} + return nil, &object.Error{Message: fmt.Sprintf("Pakeji %s ina makosa yafuatayo:\n%s", file, strings.Join(p.Errors(), "\n"))} } scope := object.NewEnvironment() diff --git a/evaluator/in.go b/evaluator/in.go index 446b35c..22bec49 100644 --- a/evaluator/in.go +++ b/evaluator/in.go @@ -3,7 +3,7 @@ package evaluator import ( "strings" - "github.com/AvicennaJr/Nuru/object" + "github.com/NuruProgramming/Nuru/object" ) func evalInExpression(left, right object.Object, line int) object.Object { diff --git a/evaluator/index.go b/evaluator/index.go index 07945f0..ee59c97 100644 --- a/evaluator/index.go +++ b/evaluator/index.go @@ -1,6 +1,6 @@ package evaluator -import "github.com/AvicennaJr/Nuru/object" +import "github.com/NuruProgramming/Nuru/object" func evalIndexExpression(left, index object.Object, line int) object.Object { switch { @@ -32,7 +32,7 @@ func evalDictIndexExpression(dict, index object.Object, line int) object.Object key, ok := index.(object.Hashable) if !ok { - return newError("Mstari %d: Samahani, %s haitumiki kama key", line, index.Type()) + return newError("Mstari %d: Samahani, %s haitumiki kama ufunguo", line, index.Type()) } pair, ok := dictObject.Pairs[key.HashKey()] @@ -41,4 +41,4 @@ func evalDictIndexExpression(dict, index object.Object, line int) object.Object } return pair.Value -} \ No newline at end of file +} diff --git a/evaluator/infix.go b/evaluator/infix.go index 33fa484..2e51052 100644 --- a/evaluator/infix.go +++ b/evaluator/infix.go @@ -4,10 +4,13 @@ import ( "math" "strings" - "github.com/AvicennaJr/Nuru/object" + "github.com/NuruProgramming/Nuru/object" ) func evalInfixExpression(operator string, left, right object.Object, line int) object.Object { + if right == nil { + return newError("Mstari %d: Umekosea hapa", line) + } if left == nil { return newError("Mstari %d: Umekosea hapa", line) } @@ -90,7 +93,7 @@ func evalInfixExpression(operator string, left, right object.Object, line int) o line, left.Type(), operator, right.Type()) default: - return newError("Mstari %d: Operesheni Haielweki: %s %s %s", + return newError("Mstari %d: Operesheni Haieleweki: %s %s %s", line, left.Type(), operator, right.Type()) } } @@ -132,7 +135,7 @@ func evalFloatIntegerInfixExpression(operator string, left, right object.Object, case "!=": return nativeBoolToBooleanObject(leftVal != rightVal) default: - return newError("Mstari %d: Operesheni Haielweki: %s %s %s", + return newError("Mstari %d: Operesheni Haieleweki: %s %s %s", line, left.Type(), operator, right.Type()) } @@ -156,7 +159,7 @@ func evalStringInfixExpression(operator string, left, right object.Object, line case "!=": return nativeBoolToBooleanObject(leftVal != rightVal) default: - return newError("Mstari %d: Operesheni Haielweki: %s %s %s", line, left.Type(), operator, right.Type()) + return newError("Mstari %d: Operesheni Haieleweki: %s %s %s", line, left.Type(), operator, right.Type()) } } @@ -170,7 +173,7 @@ func evalBooleanInfixExpression(operator string, left, right object.Object, line case "||": return nativeBoolToBooleanObject(leftVal || rightVal) default: - return newError("Mstari %d: Operesheni Haielweki: %s %s %s", line, left.Type(), operator, right.Type()) + return newError("Mstari %d: Operesheni Haieleweki: %s %s %s", line, left.Type(), operator, right.Type()) } } @@ -202,7 +205,7 @@ func evalFloatInfixExpression(operator string, left, right object.Object, line i case "!=": return nativeBoolToBooleanObject(leftVal != rightVal) default: - return newError("Mstari %d: Operesheni Haielweki: %s %s %s", + return newError("Mstari %d: Operesheni Haieleweki: %s %s %s", line, left.Type(), operator, right.Type()) } } @@ -219,7 +222,7 @@ func evalIntegerInfixExpression(operator string, left, right object.Object, line case "*": return &object.Integer{Value: leftVal * rightVal} case "**": - return &object.Integer{Value: int64(math.Pow(float64(leftVal), float64(rightVal)))} + return &object.Float{Value: float64(math.Pow(float64(leftVal), float64(rightVal)))} case "/": x := float64(leftVal) / float64(rightVal) if math.Mod(x, 1) == 0 { @@ -242,7 +245,7 @@ func evalIntegerInfixExpression(operator string, left, right object.Object, line case "!=": return nativeBoolToBooleanObject(leftVal != rightVal) default: - return newError("Mstari %d: Operesheni Haielweki: %s %s %s", + return newError("Mstari %d: Operesheni Haieleweki: %s %s %s", line, left.Type(), operator, right.Type()) } } diff --git a/evaluator/method.go b/evaluator/method.go index 5109f9d..2bf2bd6 100644 --- a/evaluator/method.go +++ b/evaluator/method.go @@ -1,8 +1,8 @@ package evaluator import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/object" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/object" ) func evalMethodExpression(node *ast.MethodExpression, env *object.Environment) object.Object { diff --git a/evaluator/package.go b/evaluator/package.go index e7cc020..07e9bee 100644 --- a/evaluator/package.go +++ b/evaluator/package.go @@ -1,8 +1,8 @@ package evaluator import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/object" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/object" ) func evalPackage(node *ast.Package, env *object.Environment) object.Object { diff --git a/evaluator/postfix.go b/evaluator/postfix.go index ea90a88..14763d5 100644 --- a/evaluator/postfix.go +++ b/evaluator/postfix.go @@ -1,8 +1,8 @@ package evaluator import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/object" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/object" ) func evalPostfixExpression(env *object.Environment, operator string, node *ast.PostfixExpression) object.Object { @@ -37,4 +37,4 @@ func evalPostfixExpression(env *object.Environment, operator string, node *ast.P default: return newError("Haifahamiki: %s", operator) } -} \ No newline at end of file +} diff --git a/evaluator/prefix.go b/evaluator/prefix.go index 4bb9f56..f46ca91 100644 --- a/evaluator/prefix.go +++ b/evaluator/prefix.go @@ -1,6 +1,6 @@ package evaluator -import "github.com/AvicennaJr/Nuru/object" +import "github.com/NuruProgramming/Nuru/object" func evalMinusPrefixOperatorExpression(right object.Object, line int) object.Object { switch obj := right.(type) { @@ -12,7 +12,7 @@ func evalMinusPrefixOperatorExpression(right object.Object, line int) object.Obj return &object.Float{Value: -obj.Value} default: - return newError("Mstari %d: Operesheni Haielweki: -%s", line, right.Type()) + return newError("Mstari %d: Operesheni Haieleweki: -%s", line, right.Type()) } } func evalPlusPrefixOperatorExpression(right object.Object, line int) object.Object { @@ -25,7 +25,7 @@ func evalPlusPrefixOperatorExpression(right object.Object, line int) object.Obje return &object.Float{Value: obj.Value} default: - return newError("Mstari %d: Operesheni Haielweki: +%s", line, right.Type()) + return newError("Mstari %d: Operesheni Haieleweki: +%s", line, right.Type()) } } @@ -38,6 +38,6 @@ func evalPrefixExpression(operator string, right object.Object, line int) object case "+": return evalPlusPrefixOperatorExpression(right, line) default: - return newError("Mstari %d: Operesheni haieleweki: %s%s", line, operator, right.Type()) + return newError("Mstari %d: Operesheni Haieleweki: %s%s", line, operator, right.Type()) } } diff --git a/evaluator/property.go b/evaluator/property.go index b68199f..c935c4f 100644 --- a/evaluator/property.go +++ b/evaluator/property.go @@ -1,8 +1,8 @@ package evaluator import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/object" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/object" ) func evalPropertyExpression(node *ast.PropertyExpression, env *object.Environment) object.Object { @@ -58,6 +58,6 @@ func evalPropertyAssignment(name *ast.PropertyExpression, val object.Object, env obj.Env.Set(prop, val) return NULL default: - return newError("Imeshindikana ku assign kwenye package %s", left.Type()) + return newError("Imeshindikana kuweka kwenye pakiti %s", left.Type()) } } diff --git a/evaluator/switch.go b/evaluator/switch.go index 53fe6f4..5963d6d 100644 --- a/evaluator/switch.go +++ b/evaluator/switch.go @@ -1,8 +1,8 @@ package evaluator import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/object" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/object" ) func evalSwitchStatement(se *ast.SwitchExpression, env *object.Environment) object.Object { @@ -27,4 +27,4 @@ func evalSwitchStatement(se *ast.SwitchExpression, env *object.Environment) obje } } return nil -} \ No newline at end of file +} diff --git a/evaluator/type.go b/evaluator/type.go new file mode 100644 index 0000000..43a3fe0 --- /dev/null +++ b/evaluator/type.go @@ -0,0 +1,72 @@ +package evaluator + +import ( + "strconv" + + "github.com/NuruProgramming/Nuru/object" +) + +func convertToInteger(obj object.Object) object.Object { + switch obj := obj.(type) { + case *object.Integer: + return obj + case *object.Float: + return &object.Integer{Value: int64(obj.Value)} + case *object.String: + i, err := strconv.ParseInt(obj.Value, 10, 64) + if err != nil { + return newError("Haiwezi kubadilisha '%s' kuwa NAMBA", obj.Value) + } + return &object.Integer{Value: i} + case *object.Boolean: + if obj.Value { + return &object.Integer{Value: 1} + } + return &object.Integer{Value: 0} + default: + return newError("Haiwezi kubadilisha %s kuwa NAMBA", obj.Type()) + } +} + +func convertToFloat(obj object.Object) object.Object { + switch obj := obj.(type) { + case *object.Float: + return obj + case *object.Integer: + return &object.Float{Value: float64(obj.Value)} + case *object.String: + f, err := strconv.ParseFloat(obj.Value, 64) + if err != nil { + return newError("Haiwezi kubadilisha '%s' kuwa DESIMALI", obj.Value) + } + return &object.Float{Value: f} + case *object.Boolean: + if obj.Value { + return &object.Float{Value: 1.0} + } + return &object.Float{Value: 0.0} + default: + return newError("Haiwezi kubadilisha %s kuwa DESIMALI", obj.Type()) + } +} + +func convertToString(obj object.Object) object.Object { + return &object.String{Value: obj.Inspect()} +} + +func convertToBoolean(obj object.Object) object.Object { + switch obj := obj.(type) { + case *object.Boolean: + return obj + case *object.Integer: + return &object.Boolean{Value: obj.Value != 0} + case *object.Float: + return &object.Boolean{Value: obj.Value != 0} + case *object.String: + return &object.Boolean{Value: len(obj.Value) > 0} + case *object.Null: + return &object.Boolean{Value: false} + default: + return &object.Boolean{Value: true} + } +} diff --git a/evaluator/while.go b/evaluator/while.go index ffe76d3..89a3a3b 100644 --- a/evaluator/while.go +++ b/evaluator/while.go @@ -1,8 +1,8 @@ package evaluator import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/object" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/object" ) func evalWhileExpression(we *ast.WhileExpression, env *object.Environment) object.Object { diff --git a/examples/Astart.nr b/examples/Astart.nr new file mode 100644 index 0000000..2ff03bd --- /dev/null +++ b/examples/Astart.nr @@ -0,0 +1,179 @@ +/*############ A*(A-star) Algorithm ############## + + By @VictorKariuki + + https://github.com/VictorKariuki + +################################################*/ + + +// create a list of numbers +fanya list = unda(first,last,interval){ + fanya list = [first]; + fanya i = first + interval; + wakati(i < last){ + list.sukuma(i) + i+=interval; + } + rudisha list; +} + +// Maths functions +// find the absolute value of a number +fanya abs_namba = unda(namba){ + kama(namba < 0){ + rudisha -1 * namba; + } + + rudisha namba; +} + +// square a number +fanya square = unda(n, i, j){ + fanya kati = (i+j)/2; + fanya mul = kati * kati; + fanya abs_diff = abs_namba(mul-n); + + kama (mul == n || abs_diff < 0.00001){ + rudisha kati; + }au kama(mul < n){ + rudisha square(n,kati,j) + }au{ + rudisha square(n,i,kati) + } +} + +// find the square root of a number +fanya sqrt = unda(namba){ + kwa i ktk list(0,namba,1) { + kama((i*i )== namba){ + rudisha i; + }au kama ((i*i )> namba){ + rudisha square(namba,i-1,i) + } + } +} + +// Main function +fanya aStar = unda(start, goal) { + // Initialize the open and closed lists + fanya openList = [start]; + fanya closedList = []; + + fanya reconstructPath = unda(node) { + fanya path = [node]; + wakati (node["parent"]) { + path = [node["parent"]] + path; + node = node["parent"]; + } + rudisha path; + } + + fanya heuristic = unda(node1, node2) { + // Calculate the Euclidean distance between the nodes' positions + fanya dx = node1["x"] - node2["x"]; + fanya dy = node1["y"] - node2["y"]; + rudisha sqrt(dx * dx + dy * dy); + } + + fanya findMinNode = unda(openList) { + fanya i = 1; + fanya minNode = openList[0]; + + wakati (i < openList.idadi()) { + fanya node = openList[i]; + kama (node["f"] < minNode["f"]) { + minNode = node; + } + i++ + } + + rudisha minNode; + } + + fanya removeNodeFromArray = unda(array, node) { + fanya newArray = []; + fanya i = 1; + wakati (i < array.idadi()) { + kama (array[i] != node) { + newArray.sukuma(array[i]); + } + i++; + } + rudisha newArray; + } + + fanya urefu = unda(node1, node2) { + // Assume all edges have a cost of 1 + rudisha 1; + } + + // Initialize the g and f scores of the starting node + start["g"] = 0; + start["f"] = start["g"] + heuristic(start, goal); + + + + // Start the search loop + wakati (openList.idadi() > 0) { + // Find the node with the lowest f score in the open list + fanya current = findMinNode(openList); + + // Check kama the goal node has been reached + kama (current == goal) { + rudisha reconstructPath(current); + } + + // Move the current node from the open to the closed list + openList = removeNodeFromArray(openList, current); + + closedList.sukuma(current); + + // Explore the neighbors of the current node + kwa neighbor ktk current["neighbors"] { + // Skip neighbors that are in the closed list + kama (neighbor ktk closedList) { + endelea + } + + // Calculate the tentative g score of the neighbor + fanya tentativeG = start["g"] + urefu(current, neighbor); + + // Check kama the neighbor is in the open list + fanya tentativeIsBetter = sikweli; + kama (!(neighbor ktk openList)) { + openList.sukuma(neighbor); + tentativeIsBetter = kweli; + } au kama (tentativeG < neighbor["g"]) { + tentativeIsBetter = kweli; + } + + // Update the neighbor's g score kama the tentative score is better + kama (tentativeIsBetter) { + neighbor["g"] = tentativeG; + neighbor["f"] = neighbor["g"] + heuristic(neighbor, goal); + neighbor["parent"] = current; + } + } + } + + // kama the open list is empty, no path was found + rudisha tupu; +} + +// Define the nodes of the graph +fanya nodeA = { "x": 0, "y": 0, "neighbors": [] }; +fanya nodeB = { "x": 1, "y": 2, "neighbors": [] }; +fanya nodeC = { "x": 3, "y": 1, "neighbors": [] }; +fanya nodeD = { "x": 4, "y": 3, "neighbors": [] }; + +// Define the edges between the nodes +nodeA["neighbors"] = [nodeB]; +nodeB["neighbors"] = [nodeA, nodeC]; +nodeC["neighbors"] = [nodeB, nodeD]; +nodeD["neighbors"] = [nodeC]; + +// Call the A* function with the start and goal nodes and the heuristic and distance functions +//fanya path = aStar(nodeA, nodeC); + +andika(nodeA); \ No newline at end of file diff --git a/examples/perceptron.nr b/examples/perceptron.nr new file mode 100644 index 0000000..bc01b54 --- /dev/null +++ b/examples/perceptron.nr @@ -0,0 +1,188 @@ +tumia hisabati + +// Mbinu za Kupanga +//orodhesha(kwanza, mwisho, umbali), huunda orodha ya nambari na umbali uliowekwa kati yao. +fanya orodhesha = unda(kwanza, mwisho, umbali){ + fanya orodha = [kwanza]; + fanya i = kwanza + umbali; + wakati(i < mwisho){ + orodha.sukuma(i); + i += umbali; + } + rudisha orodha; +} + +// Kuanzisha uzani bila mpangilio +fanya mizani = [ + hisabati.random() * 2 - 1, + hisabati.random() * 2 - 1, + hisabati.random() * 2 - 1 +]; + +// Undo la uanzishaji wa Sigmoid +fanya sigmoid = unda(vekta) { + fanya tokeo = []; + kwa v ktk vekta { + tokeo.sukuma(1 / (1 + hisabati.exp(-1 * v))); + } + rudisha tokeo; +} + +// Derivative ya undo la sigmoid +fanya sigmoidDerivative = unda(vekta) { + andika("vekta: ",vekta) + fanya tokeo = []; + kwa v ktk vekta { + tokeo.sukuma(v * (1 - v)); + } + + rudisha tokeo; +} + +fanya kuzidishaMatrikiVekta = unda(matriki, vekta) { + fanya tokeo = []; + kwa row ktk matriki { + fanya jamii = 0; + kwa j, kipengee ktk row { + jamii += kipengee * vekta[j]; + } + tokeo.sukuma(jamii); + } + rudisha tokeo; +} + +fanya zidishaKwaNukta = unda(safu1, safu2) { + // Angalia ikiwa safu zina urefu sawa + kama (safu1.idadi() != safu2.idadi()) { + andika("Safu lazima ziwe na urefu sawa kwa kuzidisha kwa busara ya kipengele."); + } + + // Perform element-wise multiplication + fanya tokeo = []; + kwa i, kipengee ktk safu1 { + tokeo.sukuma(kipengee * safu2[i]); + } + rudisha tokeo; +} + +// Songa mbele kupitia mtandao wa neva +fanya waza = unda(pembejeo, mizani) { + fanya jumlaYaUzani = sigmoid(kuzidishaMatrikiVekta(pembejeo, mizani)); + rudisha jumlaYaUzani; +} + +fanya badiliMatriki = unda(matrix) { + // Pata idadi ya safu mlalo na safu wima katika matrix asili + fanya nambari_ya_safu_mlalo = matrix.idadi(); + fanya nambari_ya_safu_wima = matrix[0].idadi(); + + // Unda matrix mpya na safu mlalo na safu wima zilizobadilishwa + fanya matrikiIliyobadili = []; + + // Pita ndani ya safu wima + kwa safu_wima_ya, safuW ktk orodhesha(0, nambari_ya_safu_wima, 1){ + // Anzisha safu mlalo mpya kwa matriki iliyopitishwa + fanya transposed_safu_mlalo = []; + + // Pita ndani ya safu mlalo + kwa safu_mlalo_ya, safu ktk orodhesha(0, nambari_ya_safu_mlalo, 1){ + // Sukuma kipengele kwenye safu wima ya sasa na safu mlalo hadi safu iliyopitishwa + transposed_safu_mlalo.sukuma(matrix[safu_mlalo_ya][safu_wima_ya]); + } + + // Sukuma safu mlalo iliyopitishwa kwenye matriki lililopitishwa + matrikiIliyobadili.sukuma(transposed_safu_mlalo); + } + + rudisha matrikiIliyobadili; +} + +// Funza mtandao wa neva +fanya funza = unda(mizani, mafunzoPembejeo, matokeoYaMafunzo, marudioYaMafunzo) { + fanya kurudia = 0 + + andika('\nmafunzoPembejeo: '); + andika(mafunzoPembejeo); + + andika('\nmatokeoYaMafunzo: '); + andika(matokeoYaMafunzo); + + + fanya orodha = orodhesha(0, marudioYaMafunzo, 1) + // andika("orodha: ",orodha) + + kwa i ktk orodha{ + andika('\n\nkurudia: '); + andika(i); + // Pitisha mafunzo yaliyowekwa kupitia mtandao wa neva + fanya pato = waza(mafunzoPembejeo, mizani); + + andika('\npato: '); + andika(pato); + + // Kuhesabu kiwango cha upungufu + fanya upungufu = []; + kwa i, kipengee ktk matokeoYaMafunzo { + upungufu.sukuma(kipengee - pato[i]); + } + + andika('\nupungufu: '); + andika(upungufu); + + fanya sigmoidDerivative_ya_pato = sigmoidDerivative(pato) + + andika('\nsigmoidDerivative tokeo: '); + andika(sigmoidDerivative_ya_pato); + + fanya zidishaKwaNukta_tokeo = zidishaKwaNukta(upungufu, sigmoidDerivative_ya_pato); + + andika('\nzidishaKwaNukta tokeo: '); + andika(zidishaKwaNukta_tokeo); + + fanya mafunzoPembejeoYaliyobadili = badiliMatriki(mafunzoPembejeo) + + andika('\nmafunzo pembejeo yaliyobadili: '); + andika(mafunzoPembejeoYaliyobadili); + + // Kuzidisha upungufu kwa pembejeo na upinde rangi ya kitendakazi cha sigmoid + // Uzito mdogo wa ujasiri hurekebishwa zaidi kupitia asili ya kazi + fanya marekebisho = kuzidishaMatrikiVekta(mafunzoPembejeo, zidishaKwaNukta_tokeo); + andika('\nmarekebisho tokeo: '); + andika(marekebisho); + + + // Rekebisha uzani + kwa i, j ktk mizani { + mizani[i] = mizani[i] + marekebisho[i]; + } + + andika('\nmizani mpya: '); + andika(mizani); + kurudia++ + } + + rudisha mizani; +} + + +andika('\nMizani ya Kuanzisha isiyo na mpangilio: '); +andika(mizani); + +// Seti ya mafunzo +fanya mafunzoPembejeo = [[0, 0, 1], [1, 1, 1], [1, 0, 1], [0, 1, 1]]; +fanya matokeoYaMafunzo = [0, 1, 1, 0]; + +// Funza mtandao wa neva +fanya mafunzoMizani = funza(mizani, mafunzoPembejeo, matokeoYaMafunzo, 10000); + +andika('\nMizani baada ya mafunzo:'); +andika(mafunzoMizani); + +// Ingizo la mtumiaji kwa hali mpya +fanya A = 0; +fanya B = 0; +fanya C = 1; + +andika('\nHali mpya: data ya pembejeo = ', A, B, C); +andika('\nData ya pato:'); +andika(waza([[A, B, C]], mafunzoMizani)); diff --git a/examples/reduce.nr b/examples/reduce.nr new file mode 100644 index 0000000..2f09d00 --- /dev/null +++ b/examples/reduce.nr @@ -0,0 +1,34 @@ +fanya reduce = unda(iterator, callback, initialValue) { + fanya accumulator = initialValue; + + kwa thamani ktk iterator { + accumulator = callback(accumulator, thamani); + } + + rudisha accumulator; +} + +fanya list = [1,2,3,4,5]; +fanya employees = [{"salary":120},{"salary":135},{"salary":140}] + +fanya sum = unda(acc,value){ + rudisha acc + value; +} + +fanya mul = unda(acc,value){ + rudisha acc * value; +} + +fanya sumSalo = unda(acc,value){ + rudisha acc + value["salary"]; +} + +fanya sumSaloWithTax = unda(acc,value){ + rudisha acc + (value["salary"] * (1-0.34)); +} + +andika(reduce(list,sum,0)) +andika(reduce(list,mul,1)) + +andika(reduce(employees,sumSalo,0)) +andika(reduce(employees,sumSaloWithTax,0)) \ No newline at end of file diff --git a/examples/sarufi.nr b/examples/sarufi.nr index 8c19e51..39c7419 100644 --- a/examples/sarufi.nr +++ b/examples/sarufi.nr @@ -1,32 +1,32 @@ tumia mtandao tumia jsoni pakeji sarufi { - andaa = unda(file) { - config = fungua(file) - configString = config.soma() - configDict = jsoni.dikodi(configString) - clientID = configDict["client_id"] - clientSecret = configDict["client_secret"] - params = {"client_id": clientID, "client_secret": clientSecret} - tokenString = mtandao.tuma(yuareli="https://api.sarufi.io/api/access_token", mwili=params) - tokenDict = jsoni.dikodi(tokenString) - @.token = tokenDict["access_token"] - @.Auth = "Bearer " + @.token - } + andaa = unda(file) { + config = fungua(file) + configString = config.soma() + configDict = jsoni.dikodi(configString) + clientID = configDict["client_id"] + clientSecret = configDict["client_secret"] + params = {"client_id": clientID, "client_secret": clientSecret} + tokenString = mtandao.tuma(yuareli="https://api.sarufi.io/api/access_token", mwili=params) + tokenDict = jsoni.dikodi(tokenString) + @.token = tokenDict["access_token"] + @.Auth = "Bearer " + @.token + } - tokenYangu = unda() { - rudisha @.token - } + tokenYangu = unda() { + rudisha @.token + } - tengenezaChatbot = unda(data) { - majibu = mtandao.tuma(yuareli="https://api.sarufi.io/chatbot", vichwa={"Authorization": @.Auth}, mwili = data) - rudisha majibu - } + tengenezaChatbot = unda(data) { + majibu = mtandao.tuma(yuareli="https://api.sarufi.io/chatbot", vichwa={"Authorization": @.Auth}, mwili = data) + rudisha majibu + } - pataChatbotZote = unda() { - majibu = mtandao.peruzi(yuareli="https://api.sarufi.io/chatbots", vichwa={"Authorization": @.Auth}) - rudisha majibu - } - } + pataChatbotZote = unda() { + majibu = mtandao.peruzi(yuareli="https://api.sarufi.io/chatbots", vichwa={"Authorization": @.Auth}) + rudisha majibu + } +} diff --git a/extensions/README.md b/extensions/README.md index b466671..6b8ccb2 100644 --- a/extensions/README.md +++ b/extensions/README.md @@ -2,4 +2,16 @@ ## [VSCODE](./vscode/) -Nuru syntax highlighting on VSCode \ No newline at end of file +Nuru syntax highlighting on VSCode + +## [VIM](./vim) + +The file contained herein has a basic syntax highlight for vim. +The file should be saved in `$HOME/.vim/syntax/nuru.vim`. +You should add the following line to your `.vimrc` or the appropriate location: + +```vim +au BufRead,BufNewFile *.nr set filetype=nuru +``` + +Only basic syntax highlighting is provided by the script. diff --git a/extensions/vim/syntax/nuru.vim b/extensions/vim/syntax/nuru.vim new file mode 100644 index 0000000..a3d60f0 --- /dev/null +++ b/extensions/vim/syntax/nuru.vim @@ -0,0 +1,51 @@ +" Sintaksia ya nuru kwenye programu ya "vim" +" Lugha: Nuru + +" Maneno tengwa +syntax keyword nuruKeyword unda pakeji rudisha vunja endelea tupu +syntax keyword nuruType fanya +syntax keyword nuruBool kweli sikweli +syntax keyword nuruConditional kama sivyo au +syntax match nuruComparision /[!\|<>]/ +syntax keyword nuruLoop ktk while badili +syntax keyword nuruLabel ikiwa kawaida + +" Nambari +syntax match nuruInt '[+-]\d\+' contained display +syntax match nuruFloat '[+-]\d+\.\d*' contained display + +" Viendeshaji +syntax match nuruAssignment '=' +syntax match nuruLogicalOP /[\&!|]/ + +" Vitendakazi +syntax keyword nuruFunction andika aina jaza fungua + +" Tungo +syntax region nuruString start=/"/ skip=/\\"/ end=/"/ +syntax region nuruString start=/'/ skip=/\\'/ end=/'/ + +" Maoni +syntax match nuruComment "//.*" +syntax region nuruComment start="/\*" end="\*/" + +" Fafanua sintaksia +let b:current_syntax = "nuru" + +highlight def link nuruComment Comment +highlight def link nuruBool Boolean +highlight def link nuruFunction Function +highlight def link nuruComparision Conditional +highlight def link nuruConditional Conditional +highlight def link nuruKeyword Keyword +highlight def link nuruString String +highlight def link nuruVariable Identifier +highlight def link nuruLoop Repeat +highlight def link nuruInt Number +highlight def link nuruFloat Float +highlight def link nuruAssignment Operator +highlight def link nuruLogicalOP Operator +highlight def link nuruAriOP Operator +highlight def link nuruType Type +highlight def link nuruLabel Label + diff --git a/extensions/vscode/README.md b/extensions/vscode/README.md index 7896dd8..c0c1c79 100644 --- a/extensions/vscode/README.md +++ b/extensions/vscode/README.md @@ -15,10 +15,10 @@ This is a syntax highliting extension for Nuru on vscode. It detects `.nr` and ` ### Windows -- Copy the whole [nuru folder](https://github.com/AvicennaJr/Nuru/tree/main/extensions/vscode/nuru) and paste it in the VSCode extensions directory found in `%USERPROFILE%\.vscode\extensions` +- Copy the whole [nuru folder](https://github.com/NuruProgramming/Nuru/tree/main/extensions/vscode/nuru) and paste it in the VSCode extensions directory found in `%USERPROFILE%\.vscode\extensions` - Restart VSCode ### Linux and MacOS -- Copy the whole [nuru folder](https://github.com/AvicennaJr/Nuru/tree/main/extensions/vscode/nuru) and paste it in the VSCode extensions directory found in `~/.vscode/extensions` +- Copy the whole [nuru folder](https://github.com/NuruProgramming/Nuru/tree/main/extensions/vscode/nuru) and paste it in the VSCode extensions directory found in `~/.vscode/extensions` - Restart VSCode diff --git a/go.mod b/go.mod index c4ce957..1ea346a 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/AvicennaJr/Nuru +module github.com/NuruProgramming/Nuru go 1.18 diff --git a/lexer/lexer.go b/lexer/lexer.go index e1db11f..7d83728 100644 --- a/lexer/lexer.go +++ b/lexer/lexer.go @@ -1,7 +1,9 @@ +// This will convert the sequence of characters into a sequence of tokens + package lexer import ( - "github.com/AvicennaJr/Nuru/token" + "github.com/NuruProgramming/Nuru/token" ) type Lexer struct { @@ -13,7 +15,7 @@ type Lexer struct { } func New(input string) *Lexer { - l := &Lexer{input: []rune(input)} + l := &Lexer{input: []rune(input), line: 1} l.readChar() return l } @@ -166,6 +168,11 @@ func (l *Lexer) NextToken() token.Token { } else { tok = newToken(token.MODULUS, l.line, l.ch) } + case rune('#'): + if l.peekChar() == rune('!') && l.line == 1 { + l.skipSingleLineComment() + return l.NextToken() + } case 0: tok.Literal = "" tok.Type = token.EOF @@ -176,6 +183,11 @@ func (l *Lexer) NextToken() token.Token { tok.Type = token.LookupIdent(tok.Literal) tok.Line = l.line return tok + } else if isDigit(l.ch) && isLetter(l.peekChar()) { + tok.Literal = l.readIdentifier() + tok.Type = token.LookupIdent(tok.Literal) + tok.Line = l.line + return tok } else if isDigit(l.ch) { tok = l.readDecimal() return tok diff --git a/lexer/lexer_test.go b/lexer/lexer_test.go index 8743b2f..a9252bd 100644 --- a/lexer/lexer_test.go +++ b/lexer/lexer_test.go @@ -3,7 +3,7 @@ package lexer import ( "testing" - "github.com/AvicennaJr/Nuru/token" + "github.com/NuruProgramming/Nuru/token" ) func TestNextToken(t *testing.T) { diff --git a/main.go b/main.go index 7bc900c..ed36acb 100644 --- a/main.go +++ b/main.go @@ -5,8 +5,8 @@ import ( "os" "strings" - "github.com/AvicennaJr/Nuru/repl" - "github.com/AvicennaJr/Nuru/styles" + "github.com/NuruProgramming/Nuru/repl" + "github.com/NuruProgramming/Nuru/styles" "github.com/charmbracelet/lipgloss" ) @@ -15,8 +15,8 @@ var ( Render(` β–ˆβ–‘β–‘β€ƒβ–ˆβ–‘β–ˆβ€ƒβ–ˆβ–€β–€β€ƒβ–ˆβ–‘β–ˆβ€ƒβ–„β–€β–ˆβ€ƒ β€ƒβ–ˆβ–„β–ˆβ€ƒβ–„β–€β–ˆβ€ƒ β€ƒβ–ˆβ–„β–‘β–ˆβ€ƒβ–ˆβ–‘β–ˆβ€ƒβ–ˆβ–€β–ˆβ€ƒβ–ˆβ–‘β–ˆ β–ˆβ–„β–„β€ƒβ–ˆβ–„β–ˆβ€ƒβ–ˆβ–„β–ˆβ€ƒβ–ˆβ–€β–ˆβ€ƒβ–ˆβ–€β–ˆβ€ƒ β€ƒβ–‘β–ˆβ–‘β€ƒβ–ˆβ–€β–ˆβ€ƒ β€ƒβ–ˆβ–‘β–€β–ˆβ€ƒβ–ˆβ–„β–ˆβ€ƒβ–ˆβ–€β–„β€ƒβ–ˆβ–„β–ˆ`) - Version = styles.VersionStyle.Render("v0.5.1") - Author = styles.AuthorStyle.Render("by Avicenna") + Version = styles.VersionStyle.Render("v0.5.18") + Author = styles.AuthorStyle.Render("by Nuru Org") NewLogo = lipgloss.JoinVertical(lipgloss.Center, Title, lipgloss.JoinHorizontal(lipgloss.Center, Author, " | ", Version)) Help = styles.HelpStyle.Italic(false).Render(fmt.Sprintf(`πŸ’‘ Namna ya kutumia Nuru: %s: Kuanza programu ya Nuru @@ -38,41 +38,36 @@ func main() { help := styles.HelpStyle.Render("πŸ’‘ Tumia exit() au toka() kuondoka") fmt.Println(lipgloss.JoinVertical(lipgloss.Left, NewLogo, "\n", help)) repl.Start() - os.Exit(0) + return } if len(args) == 2 { - switch args[1] { case "msaada", "-msaada", "--msaada", "help", "-help", "--help", "-h": fmt.Println(Help) - os.Exit(0) case "version", "-version", "--version", "-v", "v", "--toleo", "-toleo": fmt.Println(NewLogo) - os.Exit(0) case "-docs", "--docs", "-nyaraka", "--nyaraka": repl.Docs() - os.Exit(0) - } + default: + file := args[1] - file := args[1] + if strings.HasSuffix(file, "nr") || strings.HasSuffix(file, ".sw") { + contents, err := os.ReadFile(file) + if err != nil { + fmt.Println(styles.ErrorStyle.Render("Error: Nuru imeshindwa kusoma faili: ", args[1])) + os.Exit(1) + } - if strings.HasSuffix(file, "nr") || strings.HasSuffix(file, ".sw") { - contents, err := os.ReadFile(file) - if err != nil { - fmt.Println(styles.ErrorStyle.Render("Error: Nuru imeshindwa kusoma faili: ", args[1])) - os.Exit(0) + repl.Read(string(contents)) + } else { + fmt.Println(styles.ErrorStyle.Render("'"+file+"'", "sii faili sahihi. Tumia faili la '.nr' au '.sw'")) + os.Exit(1) } - - repl.Read(string(contents)) - } else { - fmt.Println(styles.ErrorStyle.Render("'"+file+"'", "sii faili sahihi. Tumia faili la '.nr' au '.sw'")) - os.Exit(0) } - } else { fmt.Println(styles.ErrorStyle.Render("Error: Operesheni imeshindikana boss.")) fmt.Println(Help) - os.Exit(0) + os.Exit(1) } } diff --git a/module/hisabati.go b/module/hisabati.go new file mode 100644 index 0000000..c1d84f1 --- /dev/null +++ b/module/hisabati.go @@ -0,0 +1,731 @@ +package module + +import ( + "math" + "math/rand" + "time" + + "github.com/NuruProgramming/Nuru/object" +) + +var MathFunctions = map[string]object.ModuleFunction{ + "PI": pi, + "e": e, + "phi": phi, + "ln10": ln10, + "ln2": ln2, + "log10e": log10e, + "log2e": log2e, + "log2": log2, + "sqrt1_2": sqrt1_2, + "sqrt2": sqrt2, + "sqrt3": sqrt3, + "sqrt5": sqrt5, + "EPSILON": epsilon, + "abs": abs, + "sign": sign, + "ceil": ceil, + "floor": floor, + "sqrt": sqrt, + "cbrt": cbrt, + "root": root, + "hypot": hypot, + "random": random, + "factorial": factorial, + "round": round, + "max": max, + "min": min, + "exp": exp, + "expm1": expm1, + "log": log, + "log10": log10, + "log1p": log1p, + "cos": cos, + "sin": sin, + "tan": tan, + "acos": acos, + "asin": asin, + "atan": atan, + "cosh": cosh, + "sinh": sinh, + "tanh": tanh, + "acosh": acosh, + "asinh": asinh, + "atanh": atanh, + "atan2": atan2, +} + +var Constants = map[string]object.Object{ + "PI": &object.Float{Value: math.Pi}, + "e": &object.Float{Value: math.E}, + "phi": &object.Float{Value: (1 + math.Sqrt(5)) / 2}, + "ln10": &object.Float{Value: math.Log10E}, + "ln2": &object.Float{Value: math.Ln2}, + "log10e": &object.Float{Value: math.Log10E}, + "log2e": &object.Float{Value: math.Log2E}, + "sqrt1_2": &object.Float{Value: 1 / math.Sqrt2}, + "sqrt2": &object.Float{Value: math.Sqrt2}, + "sqrt3": &object.Float{Value: math.Sqrt(3)}, + "sqrt5": &object.Float{Value: math.Sqrt(5)}, + "EPSILON": &object.Float{Value: 2.220446049250313e-16}, +} + +func pi(args []object.Object, defs map[string]object.Object) object.Object { + return &object.Float{Value: math.Pi} +} + +func e(args []object.Object, defs map[string]object.Object) object.Object { + return &object.Float{Value: math.E} +} + +func phi(args []object.Object, defs map[string]object.Object) object.Object { + return &object.Float{Value: (1 + math.Sqrt(5)) / 2} +} + +func ln10(args []object.Object, defs map[string]object.Object) object.Object { + return &object.Float{Value: math.Log10E} +} + +func ln2(args []object.Object, defs map[string]object.Object) object.Object { + return &object.Float{Value: math.Ln2} +} + +func log10e(args []object.Object, defs map[string]object.Object) object.Object { + return &object.Float{Value: math.Log10E} +} + +func log2e(args []object.Object, defs map[string]object.Object) object.Object { + return &object.Float{Value: math.Log2E} +} + +func sqrt1_2(args []object.Object, defs map[string]object.Object) object.Object { + return &object.Float{Value: 1 / math.Sqrt2} +} + +func sqrt2(args []object.Object, defs map[string]object.Object) object.Object { + return &object.Float{Value: math.Sqrt2} +} + +func sqrt3(args []object.Object, defs map[string]object.Object) object.Object { + return &object.Float{Value: math.Sqrt(3)} +} + +func sqrt5(args []object.Object, defs map[string]object.Object) object.Object { + return &object.Float{Value: math.Sqrt(5)} +} + +func epsilon(args []object.Object, defs map[string]object.Object) object.Object { + return &object.Float{Value: 2.220446049250313e-16} +} + +func abs(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.INTEGER_OBJ && args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe namba"} + } + switch arg := args[0].(type) { + case *object.Integer: + if arg.Value < 0 { + return &object.Integer{Value: -arg.Value} + } + return arg + case *object.Float: + if arg.Value < 0 { + return &object.Float{Value: -arg.Value} + } + return arg + default: + return &object.Error{Message: "Hoja lazima iwe namba"} + } +} + +func sign(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + switch arg := args[0].(type) { + case *object.Integer: + if arg.Value == 0 { + return &object.Integer{Value: 0} + } else if arg.Value > 0 { + return &object.Integer{Value: 1} + } else { + return &object.Integer{Value: -1} + } + case *object.Float: + if arg.Value == 0 { + return &object.Integer{Value: 0} + } else if arg.Value > 0 { + return &object.Integer{Value: 1} + } else { + return &object.Integer{Value: -1} + } + default: + return &object.Error{Message: "Hoja lazima iwe namba"} + } +} + +func ceil(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.INTEGER_OBJ && args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe namba"} + } + switch arg := args[0].(type) { + case *object.Integer: + return &object.Integer{Value: arg.Value} + case *object.Float: + return &object.Integer{Value: int64(math.Ceil(arg.Value))} + default: + return &object.Error{Message: "Hoja lazima iwe namba"} + } +} + +func floor(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.INTEGER_OBJ && args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe namba"} + } + switch arg := args[0].(type) { + case *object.Integer: + return &object.Integer{Value: arg.Value} + case *object.Float: + return &object.Integer{Value: int64(math.Floor(arg.Value))} + default: + return &object.Error{Message: "Hoja lazima iwe namba"} + } +} + +func sqrt(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.INTEGER_OBJ && args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe namba"} + } + switch arg := args[0].(type) { + case *object.Integer: + return &object.Float{Value: math.Sqrt(float64(arg.Value))} + case *object.Float: + return &object.Float{Value: math.Sqrt(arg.Value)} + default: + return &object.Error{Message: "Hoja lazima iwe namba"} + } +} + +func cbrt(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.INTEGER_OBJ && args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe namba"} + } + switch arg := args[0].(type) { + case *object.Integer: + return &object.Float{Value: math.Cbrt(float64(arg.Value))} + case *object.Float: + return &object.Float{Value: math.Cbrt(arg.Value)} + default: + return &object.Error{Message: "Hoja lazima iwe namba"} + } +} + +func root(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 2 { + return &object.Error{Message: "Undo hili linahitaji hoja mbili tu"} + } + if args[0].Type() != object.INTEGER_OBJ && args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja ya kwanza lazima iwe namba"} + } + if args[1].Type() != object.INTEGER_OBJ { + return &object.Error{Message: "Hoja ya pili lazima iwe namba"} + } + base, ok := args[0].(*object.Float) + if !ok { + base = &object.Float{Value: float64(args[0].(*object.Integer).Value)} + } + exp := args[1].(*object.Integer).Value + + if exp == 0 { + return &object.Float{Value: 1.0} + } else if exp < 0 { + return &object.Error{Message: "Second Hoja lazima iwe a non-negative integer"} + } + + x := 1.0 + for i := 0; i < 10; i++ { + x = x - (math.Pow(x, float64(exp))-base.Value)/(float64(exp)*math.Pow(x, float64(exp-1))) + } + + return &object.Float{Value: x} +} + +func hypot(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) < 2 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + var sumOfSquares float64 + for _, arg := range args { + if arg.Type() != object.INTEGER_OBJ && arg.Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima ziwe namba"} + } + switch num := arg.(type) { + case *object.Integer: + sumOfSquares += float64(num.Value) * float64(num.Value) + case *object.Float: + sumOfSquares += num.Value * num.Value + } + } + return &object.Float{Value: math.Sqrt(sumOfSquares)} +} + +func factorial(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.INTEGER_OBJ { + return &object.Error{Message: "Hoja lazima iwe namba"} + } + n := args[0].(*object.Integer).Value + if n < 0 { + return &object.Error{Message: "Hoja lazima iwe a non-negative integer"} + } + result := int64(1) + for i := int64(2); i <= n; i++ { + result *= i + } + return &object.Integer{Value: result} +} + +func round(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + + num := args[0].(*object.Float).Value + return &object.Integer{Value: int64(num + 0.5)} +} + +func max(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + + arg, ok := args[0].(*object.Array) + if !ok { + return &object.Error{Message: "Hoja lazima iwe an array"} + } + + if len(arg.Elements) == 0 { + return &object.Error{Message: "Orodha haipaswi kuwa tupu"} + } + + var maxNum float64 + + for _, element := range arg.Elements { + if element.Type() != object.INTEGER_OBJ && element.Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Vipengee vya orodha lazima viwe namba"} + } + + switch num := element.(type) { + case *object.Integer: + if float64(num.Value) > maxNum { + maxNum = float64(num.Value) + } + case *object.Float: + if num.Value > maxNum { + maxNum = num.Value + } + default: + return &object.Error{Message: "Vipengee vya orodha lazima viwe namba"} + } + } + + return &object.Float{Value: maxNum} +} + +func min(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + + arg, ok := args[0].(*object.Array) + if !ok { + return &object.Error{Message: "Hoja lazima iwe an array"} + } + + if len(arg.Elements) == 0 { + return &object.Error{Message: "Orodha haipaswi kuwa tupu"} + } + + minNum := math.MaxFloat64 + + for _, element := range arg.Elements { + if element.Type() != object.INTEGER_OBJ && element.Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Vipengee vya orodha lazima viwe namba"} + } + + switch num := element.(type) { + case *object.Integer: + if float64(num.Value) < minNum { + minNum = float64(num.Value) + } + case *object.Float: + if num.Value < minNum { + minNum = num.Value + } + default: + return &object.Error{Message: "Vipengee vya orodha lazima viwe namba"} + } + } + + return &object.Float{Value: minNum} +} + +func exp(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Exp(num)} +} + +func expm1(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Expm1(num)} +} + +func log(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Log(num)} +} + +func log10(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Log10(num)} +} + +func log2(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.INTEGER_OBJ && args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe namba"} + } + + arg := extractFloatValue(args[0]) + + if arg <= 0 { + return &object.Error{Message: "Hoja lazima iwe kubwa kuliko 0"} + } + + return &object.Float{Value: math.Log2(arg)} +} + +func extractFloatValue(obj object.Object) float64 { + switch obj := obj.(type) { + case *object.Integer: + return float64(obj.Value) + case *object.Float: + return obj.Value + default: + return 0 + } +} + +func log1p(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Log1p(num)} +} + +func cos(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Cos(num)} +} + +func sin(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Sin(num)} +} + +func tan(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Tan(num)} +} + +func acos(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Acos(num)} +} + +func asin(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Asin(num)} +} + +func atan(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Atan(num)} +} + +func cosh(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Cosh(num)} +} + +func sinh(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Sinh(num)} +} + +func tanh(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Tanh(num)} +} + +func acosh(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Acosh(num)} +} + +func asinh(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Asinh(num)} +} + +func atan2(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 2 { + return &object.Error{Message: "Undo hili linahitaji hoja mbili tu."} + } + if args[0].Type() != object.INTEGER_OBJ && args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima ziwe namba"} + } + if args[1].Type() != object.INTEGER_OBJ && args[1].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima ziwe namba"} + } + + y := extractFloatValue(args[0]) + x := extractFloatValue(args[1]) + + return &object.Float{Value: math.Atan2(y, x)} +} + +func atanh(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + if len(args) != 1 { + return &object.Error{Message: "Undo hili linahitaji hoja moja tu"} + } + if args[0].Type() != object.FLOAT_OBJ { + return &object.Error{Message: "Hoja lazima iwe desimali"} + } + num := args[0].(*object.Float).Value + return &object.Float{Value: math.Atanh(num)} +} + +func random(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 { + return &object.Error{Message: "Undo hili haliruhusu ufafanuzi."} + } + + if len(args) != 0 { + return &object.Error{Message: "Undo hili halipaswi kupokea hoja."} + } + + rand.Seed(time.Now().UnixNano()) + value := rand.Float64() + + return &object.Float{Value: value} +} diff --git a/module/json.go b/module/json.go index 582359e..51a133f 100644 --- a/module/json.go +++ b/module/json.go @@ -3,7 +3,7 @@ package module import ( "encoding/json" - "github.com/AvicennaJr/Nuru/object" + "github.com/NuruProgramming/Nuru/object" ) var JsonFunctions = map[string]object.ModuleFunction{} diff --git a/module/module.go b/module/module.go index e514a87..f4c17c7 100644 --- a/module/module.go +++ b/module/module.go @@ -1,6 +1,6 @@ package module -import "github.com/AvicennaJr/Nuru/object" +import "github.com/NuruProgramming/Nuru/object" var Mapper = map[string]*object.Module{} @@ -9,4 +9,5 @@ func init() { Mapper["muda"] = &object.Module{Name: "time", Functions: TimeFunctions} Mapper["mtandao"] = &object.Module{Name: "net", Functions: NetFunctions} Mapper["jsoni"] = &object.Module{Name: "json", Functions: JsonFunctions} + Mapper["hisabati"] = &object.Module{Name: "hisabati", Functions: MathFunctions} } diff --git a/module/net.go b/module/net.go index b8edb14..421d67b 100644 --- a/module/net.go +++ b/module/net.go @@ -6,7 +6,7 @@ import ( "io/ioutil" "net/http" - "github.com/AvicennaJr/Nuru/object" + "github.com/NuruProgramming/Nuru/object" ) var NetFunctions = map[string]object.ModuleFunction{} diff --git a/module/os.go b/module/os.go index 5397d6c..53194f4 100644 --- a/module/os.go +++ b/module/os.go @@ -5,7 +5,7 @@ import ( "os/exec" "strings" - "github.com/AvicennaJr/Nuru/object" + "github.com/NuruProgramming/Nuru/object" ) var OsFunctions = map[string]object.ModuleFunction{} diff --git a/module/time.go b/module/time.go index 69789f6..a4b3258 100644 --- a/module/time.go +++ b/module/time.go @@ -5,7 +5,7 @@ import ( "strconv" "time" - "github.com/AvicennaJr/Nuru/object" + "github.com/NuruProgramming/Nuru/object" ) var TimeFunctions = map[string]object.ModuleFunction{} @@ -14,6 +14,10 @@ func init() { TimeFunctions["hasahivi"] = now TimeFunctions["lala"] = sleep TimeFunctions["tangu"] = since + TimeFunctions["leo"] = today + TimeFunctions["baada_ya"] = after + TimeFunctions["tofauti"] = diff + TimeFunctions["ongeza"] = addTime } func now(args []object.Object, defs map[string]object.Object) object.Object { @@ -80,3 +84,108 @@ func since(args []object.Object, defs map[string]object.Object) object.Object { return &object.Integer{Value: int64(durationInSeconds)} } + +func today(args []object.Object, defs map[string]object.Object) object.Object { + if len(args) != 0 || len(defs) != 0 { + return &object.Error{Message: "hatuhitaji hoja kwenye leo"} + } + + dateStr := time.Now().Format("02-01-2006") + return &object.String{Value: dateStr} +} + +func after(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 || len(args) != 1 { + return &object.Error{Message: "tunahitaji hoja moja tu kwenye baada_ya"} + } + + secondsStr := args[0].Inspect() + seconds, err := strconv.Atoi(secondsStr) + if err != nil { + return &object.Error{Message: "hoja lazima iwe namba"} + } + + future := time.Now().Add(time.Duration(seconds) * time.Second) + return &object.Time{TimeValue: future.Format("15:04:05 02-01-2006")} +} + +func diff(args []object.Object, defs map[string]object.Object) object.Object { + if len(defs) != 0 || len(args) != 2 { + return &object.Error{Message: "tunahitaji hoja mbili kwenye tofauti"} + } + + parseTime := func(o object.Object) (time.Time, error) { + switch v := o.(type) { + case *object.Time: + return time.Parse("15:04:05 02-01-2006", v.TimeValue) + case *object.String: + return time.Parse("15:04:05 02-01-2006", v.Value) + default: + return time.Time{}, fmt.Errorf("aina batili") + } + } + + t1, err1 := parseTime(args[0]) + t2, err2 := parseTime(args[1]) + + if err1 != nil || err2 != nil { + return &object.Error{Message: "tofauti inahitaji nyakati halali mbili"} + } + + diff := t1.Sub(t2).Seconds() + return &object.Integer{Value: int64(diff)} +} + + +func addTime(args []object.Object, defs map[string]object.Object) object.Object { + if len(args) != 1 { + return &object.Error{Message: "ongeza inahitaji wakati mmoja wa kuanzia"} + } + + baseTimeObj := args[0] + baseTime, err := func() (time.Time, error) { + switch t := baseTimeObj.(type) { + case *object.Time: + return time.Parse("15:04:05 02-01-2006", t.TimeValue) + case *object.String: + return time.Parse("15:04:05 02-01-2006", t.Value) + default: + return time.Time{}, fmt.Errorf("aina ya wakati sio sahihi") + } + }() + if err != nil { + return &object.Error{Message: "wakati uliotolewa sio sahihi"} + } + + secs := getInt(defs["sekunde"]) + mins := getInt(defs["dakika"]) + hours := getInt(defs["masaa"]) + days := getInt(defs["siku"]) + weeks := getInt(defs["wiki"]) + months := getInt(defs["miezi"]) + years := getInt(defs["miaka"]) + + result := baseTime. + Add(time.Second * time.Duration(secs)). + Add(time.Minute * time.Duration(mins)). + Add(time.Hour * time.Duration(hours)). + AddDate(years, months, days+(weeks*7)) + + return &object.Time{TimeValue: result.Format("15:04:05 02-01-2006")} +} + +func getInt(obj object.Object) int { + if obj == nil { + return 0 + } + switch o := obj.(type) { + case *object.Integer: + return int(o.Value) + case *object.String: + n, err := strconv.Atoi(o.Value) + if err == nil { + return n + } + } + return 0 +} diff --git a/object/array.go b/object/array.go index eff0dcf..6bdc41d 100644 --- a/object/array.go +++ b/object/array.go @@ -15,8 +15,12 @@ func (ao *Array) Inspect() string { var out bytes.Buffer elements := []string{} - for _, e := range ao.Elements { - elements = append(elements, e.Inspect()) + if len(ao.Elements) != 0 { + for _, e := range ao.Elements { + if e.Inspect() != "" { + elements = append(elements, e.Inspect()) + } + } } out.WriteString("[") diff --git a/object/file.go b/object/file.go index c9aa930..a502c9f 100644 --- a/object/file.go +++ b/object/file.go @@ -1,8 +1,12 @@ package object +import ( + "os" +) + type File struct { Filename string - Content string // To read the file + Content string } func (f *File) Type() ObjectType { return FILE_OBJ } @@ -11,6 +15,10 @@ func (f *File) Method(method string, args []Object) Object { switch method { case "soma": return f.read(args) + case "andika": + return f.write(args) + case "ongeza": + return f.append(args) } return nil } @@ -21,3 +29,40 @@ func (f *File) read(args []Object) Object { } return &String{Value: f.Content} } + +func (f *File) write(args []Object) Object { + if len(args) != 1 { + return newError("Samahani, tunahitaji Hoja 1, wewe umeweka %d", len(args)) + } + content, ok := args[0].(*String) + if !ok { + return newError("Samahani, hoja lazima iwe Tungo") + } + err := os.WriteFile(f.Filename, []byte(content.Value), 0644) + if err != nil { + return newError("Hitilafu katika kuandika faili: %s", err.Error()) + } + f.Content = content.Value + return &Boolean{Value: true} +} + +func (f *File) append(args []Object) Object { + if len(args) != 1 { + return newError("Samahani, tunahitaji Hoja 1, wewe umeweka %d", len(args)) + } + content, ok := args[0].(*String) + if !ok { + return newError("Samahani, hoja lazima iwe Tungo") + } + file, err := os.OpenFile(f.Filename, os.O_APPEND|os.O_WRONLY, 0644) + if err != nil { + return newError("Hitilafu katika kufungua faili: %s", err.Error()) + } + defer file.Close() + _, err = file.WriteString(content.Value) + if err != nil { + return newError("Hitilafu katika kuongeza kwa faili: %s", err.Error()) + } + f.Content += content.Value + return &Boolean{Value: true} +} diff --git a/object/function.go b/object/function.go index 444101b..f7ad6b8 100644 --- a/object/function.go +++ b/object/function.go @@ -4,7 +4,7 @@ import ( "bytes" "strings" - "github.com/AvicennaJr/Nuru/ast" + "github.com/NuruProgramming/Nuru/ast" ) type Function struct { diff --git a/object/package.go b/object/package.go index 235d02c..3b104b5 100644 --- a/object/package.go +++ b/object/package.go @@ -3,7 +3,7 @@ package object import ( "fmt" - "github.com/AvicennaJr/Nuru/ast" + "github.com/NuruProgramming/Nuru/ast" ) type Package struct { diff --git a/object/strings.go b/object/strings.go index 5a428d0..095a832 100644 --- a/object/strings.go +++ b/object/strings.go @@ -1,7 +1,9 @@ package object import ( + "fmt" "hash/fnv" + "strconv" "strings" ) @@ -39,6 +41,8 @@ func (s *String) Method(method string, args []Object) Object { return s.lower(args) case "gawa": return s.split(args) + case "panga": + return s.format(args) default: return newError("Samahani, kiendesha hiki hakitumiki na tungo (Neno)") } @@ -81,3 +85,93 @@ func (s *String) split(args []Object) Object { } return &Array{Elements: elements} } + +func (s *String) format(args []Object) Object { + value, err := formatStr(s.Value, args) + + if err != nil { + return newError(err.Error()) + } + + return &String{Value: value} +} + +func formatStr(format string, options []Object) (string, error) { + var str strings.Builder + var val strings.Builder + var check_val bool + var opts_len int = len(options) + + var escapeChar bool + + type optM struct { + val bool + obj Object + } + + var optionsMap = make(map[int]optM, opts_len) + + for i, optm := range options { + optionsMap[i] = optM{val: false, obj: optm} + } + + for _, opt := range format { + + if !escapeChar && opt == '\\' { + escapeChar = true + continue + } + + if opt == '{' && !escapeChar { + check_val = true + continue + } + + if escapeChar { + if opt != '{' && opt != '}' { + str.WriteRune('\\') + } + escapeChar = false + } + + if check_val && opt == '}' { + vstr := strings.TrimSpace(val.String()) + arrv, err := strconv.Atoi(vstr) + if err != nil { + return "", fmt.Errorf(fmt.Sprintf("Ulichopeana si NAMBA, jaribu tena: `%s'", vstr)) + } + + oVal, exists := optionsMap[arrv] + + if !exists { + return "", fmt.Errorf(fmt.Sprintf("Nambari ya chaguo unalolitaka %d ni kubwa kuliko ulizopeana (%d)", arrv, opts_len)) + } + + str.WriteString(oVal.obj.Inspect()) + optionsMap[arrv] = optM{val: true, obj: oVal.obj} + + check_val = false + val.Reset() + continue + } + + if check_val { + val.WriteRune(opt) + continue + } + + str.WriteRune(opt) + } + + if check_val { + return "", fmt.Errorf(fmt.Sprintf("Haukufunga '{', tuliokota kabla ya kufika mwisho `%s'", val.String())) + } + + for _, v := range optionsMap { + if !v.val { + return "", fmt.Errorf(fmt.Sprintf("Ulipeana hili chaguo (%s) {%s} lakini haukutumia", v.obj.Inspect(), v.obj.Type())) + } + } + + return str.String(), nil +} diff --git a/parser/arrays.go b/parser/arrays.go index 119a903..dca541d 100644 --- a/parser/arrays.go +++ b/parser/arrays.go @@ -1,8 +1,8 @@ package parser import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/token" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/token" ) func (p *Parser) parseArrayLiteral() ast.Expression { diff --git a/parser/assignEqual.go b/parser/assignEqual.go index ed560be..82d2346 100644 --- a/parser/assignEqual.go +++ b/parser/assignEqual.go @@ -3,7 +3,7 @@ package parser import ( "fmt" - "github.com/AvicennaJr/Nuru/ast" + "github.com/NuruProgramming/Nuru/ast" ) func (p *Parser) parseAssignEqualExpression(exp ast.Expression) ast.Expression { diff --git a/parser/assignment.go b/parser/assignment.go index b905329..2a4216c 100644 --- a/parser/assignment.go +++ b/parser/assignment.go @@ -3,12 +3,11 @@ package parser import ( "fmt" - "github.com/AvicennaJr/Nuru/ast" + "github.com/NuruProgramming/Nuru/ast" ) func (p *Parser) parseAssignmentExpression(exp ast.Expression) ast.Expression { switch node := exp.(type) { - // temporarily making let keyword optional case *ast.Identifier: e := &ast.Assign{ Token: p.curToken, diff --git a/parser/at.go b/parser/at.go index 65587f3..7d0c6ad 100644 --- a/parser/at.go +++ b/parser/at.go @@ -1,6 +1,6 @@ package parser -import "github.com/AvicennaJr/Nuru/ast" +import "github.com/NuruProgramming/Nuru/ast" func (p *Parser) parseAt() ast.Expression { return &ast.At{Token: p.curToken} diff --git a/parser/boolean.go b/parser/boolean.go index 9ce95e6..0d3c125 100644 --- a/parser/boolean.go +++ b/parser/boolean.go @@ -1,8 +1,8 @@ package parser import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/token" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/token" ) func (p *Parser) parseBoolean() ast.Expression { diff --git a/parser/break.go b/parser/break.go index 6c4c8ef..0bdc4a7 100644 --- a/parser/break.go +++ b/parser/break.go @@ -1,8 +1,8 @@ package parser import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/token" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/token" ) func (p *Parser) parseBreak() *ast.Break { diff --git a/parser/continue.go b/parser/continue.go index a66b85f..09b6e52 100644 --- a/parser/continue.go +++ b/parser/continue.go @@ -1,8 +1,8 @@ package parser import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/token" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/token" ) func (p *Parser) parseContinue() *ast.Continue { diff --git a/parser/dict.go b/parser/dict.go index 4b3b205..450e72a 100644 --- a/parser/dict.go +++ b/parser/dict.go @@ -1,8 +1,8 @@ package parser import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/token" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/token" ) func (p *Parser) parseDictLiteral() ast.Expression { diff --git a/parser/dot.go b/parser/dot.go index 0503d93..b46882f 100644 --- a/parser/dot.go +++ b/parser/dot.go @@ -1,8 +1,8 @@ package parser import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/token" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/token" ) func (p *Parser) parseMethod(obj ast.Expression) ast.Expression { diff --git a/parser/float.go b/parser/float.go index 77f6075..7544c21 100644 --- a/parser/float.go +++ b/parser/float.go @@ -4,7 +4,7 @@ import ( "fmt" "strconv" - "github.com/AvicennaJr/Nuru/ast" + "github.com/NuruProgramming/Nuru/ast" ) func (p *Parser) parseFloatLiteral() ast.Expression { diff --git a/parser/for.go b/parser/for.go index 7e36038..4548b7a 100644 --- a/parser/for.go +++ b/parser/for.go @@ -1,8 +1,8 @@ package parser import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/token" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/token" ) func (p *Parser) parseForExpression() ast.Expression { diff --git a/parser/function.go b/parser/function.go index 50d604e..d1f710a 100644 --- a/parser/function.go +++ b/parser/function.go @@ -1,8 +1,8 @@ package parser import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/token" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/token" ) func (p *Parser) parseFunctionLiteral() ast.Expression { diff --git a/parser/identifier.go b/parser/identifier.go index d9d5b7e..327993b 100644 --- a/parser/identifier.go +++ b/parser/identifier.go @@ -1,7 +1,7 @@ package parser import ( - "github.com/AvicennaJr/Nuru/ast" + "github.com/NuruProgramming/Nuru/ast" ) func (p *Parser) parseIdentifier() ast.Expression { diff --git a/parser/if.go b/parser/if.go index b3eccc6..fff01ed 100644 --- a/parser/if.go +++ b/parser/if.go @@ -1,8 +1,8 @@ package parser import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/token" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/token" ) func (p *Parser) parseIfExpression() ast.Expression { diff --git a/parser/import.go b/parser/import.go index 2a8027b..c2f75f7 100644 --- a/parser/import.go +++ b/parser/import.go @@ -1,8 +1,8 @@ package parser import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/token" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/token" ) func (p *Parser) parseImport() ast.Expression { diff --git a/parser/index.go b/parser/index.go index 9104bc6..6e3cab7 100644 --- a/parser/index.go +++ b/parser/index.go @@ -1,8 +1,8 @@ package parser import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/token" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/token" ) func (p *Parser) parseIndexExpression(left ast.Expression) ast.Expression { diff --git a/parser/integer.go b/parser/integer.go index c35bcd2..46d648a 100644 --- a/parser/integer.go +++ b/parser/integer.go @@ -4,7 +4,7 @@ import ( "fmt" "strconv" - "github.com/AvicennaJr/Nuru/ast" + "github.com/NuruProgramming/Nuru/ast" ) func (p *Parser) parseIntegerLiteral() ast.Expression { diff --git a/parser/null.go b/parser/null.go index 2f4c869..1cf11b5 100644 --- a/parser/null.go +++ b/parser/null.go @@ -1,7 +1,7 @@ package parser import ( - "github.com/AvicennaJr/Nuru/ast" + "github.com/NuruProgramming/Nuru/ast" ) func (p *Parser) parseNull() ast.Expression { diff --git a/parser/package.go b/parser/package.go index 7d3c6a0..7e5a6c6 100644 --- a/parser/package.go +++ b/parser/package.go @@ -1,8 +1,8 @@ package parser import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/token" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/token" ) func (p *Parser) parsePackage() ast.Expression { diff --git a/parser/parser.go b/parser/parser.go index d5365ed..0bcf5f8 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -3,13 +3,12 @@ package parser import ( "fmt" - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/lexer" - "github.com/AvicennaJr/Nuru/token" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/lexer" + "github.com/NuruProgramming/Nuru/token" ) const ( - // Think of BODMAS _ int = iota LOWEST ASSIGN // = @@ -89,7 +88,6 @@ func (p *Parser) registerPostfix(tokenType token.TokenType, fn postfixParseFn) { func New(l *lexer.Lexer) *Parser { p := &Parser{l: l, errors: []string{}} - // Gotta set these niggas p.nextToken() p.nextToken() diff --git a/parser/parser_test.go b/parser/parser_test.go index 91e00ee..50e880e 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -4,8 +4,8 @@ import ( "fmt" "testing" - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/lexer" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/lexer" ) func TestLetStatements(t *testing.T) { diff --git a/parser/statements.go b/parser/statements.go index 8718130..7e07f23 100644 --- a/parser/statements.go +++ b/parser/statements.go @@ -3,12 +3,11 @@ package parser import ( "fmt" - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/token" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/token" ) func (p *Parser) parseStatement() ast.Statement { - // Remember to add switch statements to the language switch p.curToken.Type { case token.LET: return p.parseLetStatement() diff --git a/parser/string.go b/parser/string.go index cfd90f2..8a023fa 100644 --- a/parser/string.go +++ b/parser/string.go @@ -1,7 +1,7 @@ package parser import ( - "github.com/AvicennaJr/Nuru/ast" + "github.com/NuruProgramming/Nuru/ast" ) func (p *Parser) parseStringLiteral() ast.Expression { diff --git a/parser/switch.go b/parser/switch.go index 88ce460..ebffc63 100644 --- a/parser/switch.go +++ b/parser/switch.go @@ -3,8 +3,8 @@ package parser import ( "fmt" - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/token" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/token" ) func (p *Parser) parseSwitchStatement() ast.Expression { diff --git a/parser/while.go b/parser/while.go index 3ae92fc..1d7a202 100644 --- a/parser/while.go +++ b/parser/while.go @@ -1,8 +1,8 @@ package parser import ( - "github.com/AvicennaJr/Nuru/ast" - "github.com/AvicennaJr/Nuru/token" + "github.com/NuruProgramming/Nuru/ast" + "github.com/NuruProgramming/Nuru/token" ) func (p *Parser) parseWhileExpression() ast.Expression { diff --git a/repl/docs.go b/repl/docs.go index 17969ab..b8fd428 100644 --- a/repl/docs.go +++ b/repl/docs.go @@ -4,11 +4,11 @@ import ( "fmt" "strings" - "github.com/AvicennaJr/Nuru/evaluator" - "github.com/AvicennaJr/Nuru/lexer" - "github.com/AvicennaJr/Nuru/object" - "github.com/AvicennaJr/Nuru/parser" - "github.com/AvicennaJr/Nuru/styles" + "github.com/NuruProgramming/Nuru/evaluator" + "github.com/NuruProgramming/Nuru/lexer" + "github.com/NuruProgramming/Nuru/object" + "github.com/NuruProgramming/Nuru/parser" + "github.com/NuruProgramming/Nuru/styles" "github.com/charmbracelet/bubbles/key" "github.com/charmbracelet/bubbles/list" "github.com/charmbracelet/bubbles/textarea" diff --git a/repl/docs/en/README.md b/repl/docs/en/README.md index e34c64d..ae3e1c8 100644 --- a/repl/docs/en/README.md +++ b/repl/docs/en/README.md @@ -69,6 +69,10 @@ This documentation is intended for people with some experience in programming. I - [Import JSONI](json.md#import-jsoni) - [Decoding JSON with dikodi()](json.md#decoding-json-with-dikodi()) - [Encoding JSON with enkodi()](json.md#encoding-json-with-enkodi()) +- [Hisabati in nuru](hisabati.md#module-hisabati) + - [Import Hisabati](hisabati.md#usage) + - [In-built Constants](hisabati.md#1-constants) + - [In-built Methods](hisabati.md#2-methods) - [KEYWORDS](keywords.md#keywords) - [Reserved Keywords](keywords.md#reserved-keywords) - [BuiltIns](keywords.md#builtins) diff --git a/repl/docs/en/hisabati.md b/repl/docs/en/hisabati.md new file mode 100644 index 0000000..b8f4afb --- /dev/null +++ b/repl/docs/en/hisabati.md @@ -0,0 +1,257 @@ +# Module Hisabati + +Module Hisabati is a inbuilt math module by [VictorKariuki](https://github.com/VictorKariuki). + +This in-built module provides various mathematical functions and constants. It includes methods for `trigonometric functions`, `logarithmic functions`, `array operations`, and `utility functions`. + +## Usage + +To use the `hisabati` in-built module follow the steps below: + +1. You directly import the `hisabati` in-built module and any required in-built modules in your Nuru code using the `tumia` keyword. + + ```nuru + tumia hisabati + ``` + +2. Calling the in-built module methods: + + ```nuru + andika(hisabati.e()) + ``` + +## Yaliyomo + +This in-built module covers a wide range of mathematical operations, including : + +- `Basic Mathematical Functions:` +- `Hyperbolic` & `Trigonometric Functions` +- `Exponential` & `Logarithmic Functions` +- `Rounding` & `Comparison Functions` + +Here is an in-depth classification of the methods: + +1. Trigonometric Functions: + + - `cos(n)` + - `sin(n)` + - `tan(n)` + - `acos(n)` + - `asin(n)` + - `atan(n)` + - `hypot(numbers)` + +2. Hyperbolic Functions: + + - `cosh(n)` + - `sinh(n)` + - `tanh(n)` + - `acosh(n)` + - `asinh(n)` + - `atanh(n)` + +3. Exponential and Logarithmic Functions: + + - `exp(n)` + - `expm1(n)` + - `log(n)` + - `log2(n)` + - `log10(n)` + - `log1p(n)` + +4. Basic Mathematical Functions: + + - `abs(n)` + - `sqrt(n)` + - `cbrt(n)` + - `root(x, n)` + - `factorial(n)` + - `sign(n)` + +5. Rounding and Comparison Functions: + + - `ceil(n)` + - `floor(n)` + - `round(n)` + - `max(numbers)` + - `min(numbers)` + +### 1. Constants: + +- **PI**: Represents the mathematical constant `Ο€`. +- **e**: Represents `Euler's Number`. +- **phi**: Represents the `Golden Ratio`. +- **ln10**: Represents the `natural logarithm of 10`. +- **ln2**: Represents the `natural logarithm of 2`. +- **log10e**: Represents the `base 10 logarithms` of Euler's number `(e)`. +- **log2e**: Represents the `base 2 logarithm` of Euler's number` (e)`. +- **sqrt1_2**: Represents the `square root` of `1/2`. +- **sqrt2**: Represents the `square root` of `2`. +- **sqrt3**: Represents the `square root` of `3`. +- **sqrt5**: Represents the `square root` of `5`. +- **EPSILON**: Represents a small value `2.220446049250313e-16`. + +### 2. Methods: + +1. **abs(namba)** + + - Description: Calculates the absolute value of a number. + - Example: `hisabati.abs(-42)` returns `42`. + +2. **acos(n)** + + - Description: Calculates the arccosine of a number. + - Example: `hisabati.acos(0.5)` returns `1.0471975511965979`. + +3. **acosh(n)** + + - Description: Calculates the inverse hyperbolic cosine of a number. + - Example: `hisabati.acosh(2.0)` returns `1.3169578969248166`. + +4. **asin(n)** + + - Description: Calculates the arcsine of a number using the Taylor series. + - Example: `hisabati.arcsin(0.5)` returns `0.5235987755982988`. + +5. **asinh(n)** + + - Description: Calculates the inverse hyperbolic sine of a number. + - Example: `hisabati.arsinh(2.0)` returns `1.4436354751788103`. + +6. **atan(n)** + + - Description: Calculates the arctangent of a number using the Taylor series. + - Example: `hisabati.atan(1.0)` returns `0.7853981633974483`. + +7. **atan2(y, x)** + + - Description: Calculates the arctangent of the quotient of its arguments. + - Example: `hisabati.atan2(1.0, 1.0)` returns `0.7853981633974483`. + +8. **atanh(n)** + + - Description: Calculates the inverse hyperbolic tangent of a number. + - Example: `hisabati.atanh(0.5)` returns `0.5493061443340549`. + +9. **cbrt(n)** + + - Description: Calculates the cube root of a number. + - Example: `hisabati.cbrt(8)` returns `2`. + +10. **root(x, n)** + + - Description: Calculates the nth root of a number using the Newton-Raphson method. + - Example: `hisabati.root(27, 3)` returns `3`. + +11. **ceil(n)** + + - Description: Rounds up to the smallest integer greater than or equal to a given number. + - Example: `hisabati.ceil(4.3)` returns `5`. + +12. **cos(n)** + + - Description: Calculates the cosine of an angle in radians using the Taylor series. + - Example: `hisabati.cos(0.0)` returns `1`. + +13. **cosh(n)** + + - Description: Calculates the hyperbolic cosine of a number. + - Example: `hisabati.cosh(0.0)` returns `1`. + +14. **exp(n)** + + - Description: Calculates the value of Euler's number raised to the power of a given number. + - Example: `hisabati.exp(2.0)` returns `7.38905609893065`. + +15. **expm1(n)** + + - Description: Calculates Euler's number raised to the power of a number minus 1. + - Example: `hisabati.expm1(1.0)` returns `1.718281828459045`. + +16. **floor(n)** + + - Description: Rounds down to the largest integer less than or equal to a given number. + - Example: `hisabati.floor(4.7)` returns `4`. + +17. **hypot(values)** + + - Description: Calculates the square root of the sum of squares of the given values. + - Example: `hisabati.hypot([3, 4])` returns `5`. + +18. **log(n)** + + - Description: Calculates the natural logarithm of a number. + - Example: `hisabati.log(1.0)` returns `0`. + +19. **log10(n)** + + - Description: Calculates the base 10 logarithm of a number. + - Example: `hisabati.log10(100.0)` returns `2`. + +20. **log1p(n)** + + - Description: Calculates the natural logarithm of 1 plus the given number. + - Example: `hisabati.log1p(1.0)` returns `0.6931471805599453`. + +21. **log2(n)** + + - Description: Calculates the base 2 logarithm of a number. + - Example: `hisabati.log2(8)` returns `3`. + +22. **max(numbers)** + + - Description: Finds the maximum value in a list of numbers. + - Example: `hisabati.max([4, 2, 9, 5])` returns `9`. + +23. **min(numbers)** + + - Description: Finds the minimum value in a list of numbers. + - Example: `hisabati.min([4, 2, 9, 5])` returns `2`. + +24. **round(x, method)** + + - Description: Rounds a number to the nearest integer using the specified method. + - Example: `hisabati.round(4.6)` returns `5`. + +25. **sign(n)** + + - Description: Determines the sign of a number. + - Example: `hisabati.sign(-5)` returns `-1`. + +26. **sin(n)** + + - Description: Calculates the sine of an angle in radians using the Taylor series. + - Example: `hisabati.sin(1.0)` returns `0.8414709848078965`. + +27. **sinh(n)** + + - Description: Calculates the hyperbolic sine of a number. + - Example: `hisabati.sinh(1.0)` returns `1.1752011936438014`. + +28. **sqrt(n)** + + - Description: Calculates the square root of a number. + - Example: `hisabati.sqrt(4)` returns `2`. + +29. **tan(n)** + + - Description: Calculates the tangent of an angle in radians. + - Example: `hisabati.tan(1.0)` returns `1.557407724654902`. + +30. **tanh(n)** + + - Description: Calculates the hyperbolic tangent of a number. + - Example: `hisabati.tanh(1.0)` returns `0.7615941559557649`. + +31. **factorial(n)** + + - Description: Calculates the factorial of a number. + - Example: `hisabati.factorial(5)` returns `120`. + +### Contributing + +Contributions to the `module hisabati` are welcome. If you have any improvements or bug fixes, feel free to create a pull request. + +### License + +This in-built module is available under the MIT License. See the [LICENSE](LICENSE) file for more information. \ No newline at end of file diff --git a/repl/docs/en/range.md b/repl/docs/en/range.md new file mode 100644 index 0000000..32d6eac --- /dev/null +++ b/repl/docs/en/range.md @@ -0,0 +1,55 @@ +## Range Function (mfululizo) + +The `mfululizo` function generates a sequence of numbers. It can be used in loops or to create arrays of sequential numbers. + +### Syntax + +```go +mfululizo(end) +mfululizo(start, end) +mfululizo(start, end, step) +``` + +### Parameters + +- `end`: The upper limit of the sequence (exclusive). +- `start` (optional): The starting value of the sequence. Default is 0. +- `step` (optional): The increment between each number in the sequence. Default is 1. + +### Return Value + +Returns an array of integers. + +### Examples + +```go +// Generate numbers from 0 to 4 +kwa i katika mfululizo(5) { + andika(i) +} +// Output: 0 1 2 3 4 + +// Generate numbers from 1 to 9 +kwa i katika mfululizo(1, 10) { + andika(i) +} +// Output: 1 2 3 4 5 6 7 8 9 + +// Generate even numbers from 0 to 8 +kwa i katika mfululizo(0, 10, 2) { + andika(i) +} +// Output: 0 2 4 6 8 + +// Generate numbers in reverse order +kwa i katika mfululizo(10, 0, -1) { + andika(i) +} +// Output: 10 9 8 7 6 5 4 3 2 1 +``` + +### Notes + +- The `end` value is exclusive, meaning the sequence will stop before reaching this value. +- If a negative `step` is provided, `start` should be greater than `end`. +- The `step` value cannot be zero. diff --git a/repl/docs/en/time.md b/repl/docs/en/time.md index c84caac..7809afe 100644 --- a/repl/docs/en/time.md +++ b/repl/docs/en/time.md @@ -3,55 +3,100 @@ ## Importing Time To use Time in Nuru, you first have to import the `muda` module as follows: + ```so tumia muda ``` +--- + ## Time Methods -### hasahivi() -To get the current time use the the `muda.hasahivi()` method. This will return a `muda` object with the current time: +### `hasahivi()` + +To get the current time, use `muda.hasahivi()`. It returns a `muda` object with the current time in the format `HH:mm:ss dd-MM-YYYY`. + ```so tumia muda saivi = muda.hasahivi() ``` -### tangu() -Use this method to get the total time elapsed in seconds. It accepts a time object or a string in the format `HH:mm:ss dd-MM-YYYY`: +--- + +### `leo()` + +To get today’s date in the format `dd-MM-YYYY`: ```so tumia muda -sasa = muda.hasahivi() +leo = muda.leo() +``` -muda.tangu(s) // will return the elapsed time +--- -// alternatively: +### `tangu(time)` -sasa.tangu("00:00:00 01-01-1900") // will return the elapsed time in seconds since that date +Gets the total time elapsed **in seconds** from the given time to now. Accepts a `muda` object or string in `HH:mm:ss dd-MM-YYYY` format. + +```so +tumia muda + +muda_ulioyopita = muda.tangu("15:00:00 01-01-2024") ``` -### lala() +--- + +### `lala(sekunde)` + +Pauses the program for the given number of seconds: -Use lala if you want your program to sleep. It accepts one argument which is the total time to sleep in seconds: ```so -muda.lala(10) // will sleep for ten seconds +tumia muda + +muda.lala(5) // sleeps for 5 seconds ``` -### ongeza() +--- + +### `baada_ya(sekunde)` + +Returns a `muda` object representing the time after the given number of seconds from now. -Use this method to add to time, better explained with an example: ```so tumia muda -sasa = muda.hasahivi() +baadaye = muda.baada_ya(60) // one minute from now +``` + +--- + +### `tofauti(muda1, muda2)` + +Returns the difference between two time values in seconds. + +```so +tumia muda + +saa1 = muda.hasahivi() +saa2 = muda.baada_ya(30) + +tofauti = muda.tofauti(saa2, saa1) // 30 +``` + +--- + +### `ongeza(...)` + +To add time to a `muda` object. You must specify at least one of the following fields `sekunde`, `dakika`, `masaa`, `siku`, `wiki`, `miezi`, `miaka`. + +Example: +```so +tumia muda + +sasa = muda.hasahivi() kesho = sasa.ongeza(siku=1) -kesho_pia = sasa.ongeza(saa=24) mwakani = sasa.ongeza(miaka=1) -miezi_tatu_mbele = sasa.ongeza(miezi = 3) -wiki_ijayo = sasa.ongeza(siku=7) -idi = sasa.ongeza(siku=3, masaa=4, dakika=50, sekunde=3) ``` -It will return a muda object with the specified time. diff --git a/repl/docs/sw/README.md b/repl/docs/sw/README.md index 698fdad..02d28f0 100644 --- a/repl/docs/sw/README.md +++ b/repl/docs/sw/README.md @@ -1 +1,27 @@ -# NURU PROGRAMMING LANGUAGE DOCUMENTATION \ No newline at end of file +# NYARAKA YA LUGHA YA PROGRAMU YA NURU + +Hii nyaraka imeandikwa ikilenga watu wenye uzoefu na kuandika au kupanga programu. Inaelezea sintaksia, aina na namna ya kufanya operesheni mbali mbali kutumia lugha ya NURU. + +## Yaliyomo + +- [Safu Kwenye Nuru](arrays.md#arrays-in-nuru) + - [Kutengeneza Safu](arrays.md#creating-arrays) + - [Kupata na Kurekebisha vipengele vya Safu](arrays.md#accessing-and-modifying-array-elements) + - [Kuunganisha Safu](arrays.md#concatenating-arrays) + - [Kuangalia uwepo wa vipengele ndani ya safu](arrays.md#checking-for-array-membership) + - [Kupita na Kurejea kwenye safu](arrays.md#looping-over-arrays) + - [Mbinu za Safu](arrays.md#array-methods) + - [idadi()](arrays.md#idadi()) + - [sukuma()](arrays.md#sukuma()) + - [yamwisho()](arrays.md#yamwisho()) +- [Visaidia-kazi vya Nuru](builtins.md#built-in-functions-in-nuru) + - [Kisaidia-kazi andika() ](builtins.md#the-andika()-function) + - [Kisaidia-kazi jaza()](builtins.md#the-jaza()-function) + - [Kisaidia-kazi aina()](builtins.md#the-aina()-function) + - [Kisaidia-kazi fungua()](builtins.md#the-fungua()-function) +- [Maoni kwenye Nuru](comments.md#comments-in-nuru) + - [Maoni ya mstari mmoja](comments.md#single-line-comments) + - [Maoni ya mistari mingi](comments.md#multi-line-comments) +- [Kauli za masharti kwenye Nuru](ifStatements.md#conditional-statements-in-nuru) + - [Kauli ya kama](ifStatements.md#if-statement-(kama)) + - [Kauli za Au Kama na Sivyo)](ifStatements.md#else-if-and-else-blocks-(au-kama-and-sivyo)) \ No newline at end of file diff --git a/repl/docs/sw/arrays.md b/repl/docs/sw/arrays.md index bbc6434..d9fbc6b 100644 --- a/repl/docs/sw/arrays.md +++ b/repl/docs/sw/arrays.md @@ -1 +1,122 @@ -# Orodha (Arrays) \ No newline at end of file +# Orodha Au Safu Katika Nuru + +Safu katika nuru ni miundo ya data ambayo inaweza kubeba vitu vingi, ikiwa ni pamoja na aina za data tofauti tofauti kama `namba`, `tungo`, `buliani`, `vitendakazi`, na thamani `tupu`. Ukurasa huu unaangazia vipengele mbalimbali vya safu, ikiwemo namna ya kutengeneza, kuchambua, na kuzunguka ndani yake kwa kutumia vitendakazi vilivyojengwa ndani ya Nuru. + +## Kutengeneza Safu + +Kutengeneza safu, tumia mabano mraba na tenganisha kila kitu kimoja kwa kutumia mkwaju: + +```s +orodha = [1, "pili", kweli] +``` + +## Kupata na Kubadilisha Vipengele vya Safu + +Safu katika Nuru ni zero-indexed; ikimaanisha kipengele cha kwanza katika safu kina kumbukumbu namba 0. Kupata kipengele, unaweza ukatumia kumbukumbu namba yake ndani ya mabano mraba: + +```s +namba = [10, 20, 30] +jina = namba[1] // jina is 20 +``` + +Unaweza ukabadilisha kipengele katika safu kwa kutumia kumbukumbu namba yake: + +```s +namba = [10, 20, 30] +namba[1] = 25 +andika(namba) // Tokeo: [10,25,30] +``` + +## Kuunganisha Safu + +Kuunganisha safu mbili au zaidi, tumia kiendeshi `+`: + +```s +a = [1, 2, 3] +b = [4, 5, 6] +c = a + b +// c is now [1, 2, 3, 4, 5, 6] +``` + +## Kuangalia Uanachama Katika Safu + +Tumia neno msingi `ktk` kuangalia kama kipengele kipo ndani ya safu: + +```s +namba = [10, 20, 30] +andika(20 ktk namba) // Tokeo: kweli +``` + +## Kuzunguka Ndani ya Safu + +Unaweza kutumia maneno msingi `kwa` na `ktk` kuzunguka ndani ya safu. Kuzunguka ndani ya safu na kupata kipengele peke yake tumia sintaksia ifuatayo: + +```s +namba = [1, 2, 3, 4, 5] + +kwa thamani ktk namba { + andika(thamani) +} + +//Tokeo: +1 +2 +3 +4 +5 +``` + +Kuzunguka ndani ya safu na kupata kumbukumbu namba na kipengele tumia sintaksi aifuatayo: + +```s +majina = ["Juma", "Asha", "Haruna"] + +kwa idx, jina ktk majina { + andika(idx, "-", jina) +} + +//Tokeo: +0-Juma +1-Asha +2-Haruna +``` + +## Vitendakazi vya Safu + +Nuru ina vitendakazi mbalimbali vilivyojengwa ndani kwa ajili ya Safu: + +### idadi() + +`idadi()` hurudisha urefu wa safu: + +```s +a = [1, 2, 3] +urefu = a.idadi() +andika(urefu) // Tokeo: 3 +``` + +### sukuma() + +`sukuma()` huongeza kipengele kimoja au zaidi mwishoni mwa safu: + +```s +a = [1, 2, 3] +a.sukuma("s", "g") +andika(a) // Tokeo [1, 2, 3, "s", "g"] +``` + +### yamwisho() + +`yamwisho()` hurudisha kipengele cha mwisho katika safu, au `tupu` kama safu haina kitu: + +```s +a = [1, 2, 3] +mwisho = a.yamwisho() +andika(mwisho) // Tokeo: 3 + +b = [] +mwisho = b.yamwisho() +andika(mwisho) // Tokeo: tupu +``` + +Kwa kutumia taarifa hii, unaweza ukafanyakazi na safu za Nuru kwa ufanisi, kufanya iwe rahisi kuchambua mikusanyo ya data katika programu zako. diff --git a/repl/docs/sw/bools.md b/repl/docs/sw/bools.md index 16f7a44..a43a5a2 100644 --- a/repl/docs/sw/bools.md +++ b/repl/docs/sw/bools.md @@ -1 +1,97 @@ -# Kweli/Sikweli (Bools) +# Kufanya Kazi na Buliani Katika Nuru + +Vitu vyote katika Nuru ni kweli, yaani thamani yoyote ni kweli isipokua tupu and sikweli. Hutumika kutathmini semi ambazo zinarudisha kweli au sikweli. + +## Kutathmini Semi za Buliani + +### Kutathmini Semi Rahisi + +Katika Nuru, unaweza kutathmini semi rahisi zinazorudisha thamani ya buliani: + +```go +andika(1 > 2) // Matokeo: `sikweli` + +andika(1 + 3 < 10) // Matokeo: `kweli` +``` + +### Kutathmini Semi Tata + +Katika Nuru, unaweza kutumia viendeshaji vya buliani kutathmini semi tata: + +```go +a = 5 +b = 10 +c = 15 + +tokeo = (a < b) && (b < c) + +kama (tokeo) { + andika("Hali zote mbili ni kweli") +} sivyo { + andika("Angalau hali moja ni sikweli") +} +// Tokeo: "Hali zote mbili ni kweli" +``` + +Hapa tumetengeneza vibadilika vitatu a,b,c. Kisha tukatathmini semi (a < b) && (b < c). Kwa sababu semi zote mbili ni kweli, tokeo litakua "Hali zote mbili ni kweli". + +## Vitendakazi vya Buliani + +Nuru ina vitendakazi vya buliani kadhaa ambavyo unaweza ukatumia kutathmini semi: + +### Kitendakazi `&&` + +Kitendakazi `&&` hutathmini kwenda kweli kama tu vitu vyote vinavyohusika ni kweli. Kwa mfano: + +```go +andika(kweli && kweli) // Tokeo: `kweli` + +andika(kweli && sikweli) // Tokeo: `sikweli` +``` + +### Kitendakazi `||` + +Kitendakazi || hutathmini kwenda kweli kama angalau kitu kimoja kati ya vyote vinavyohusika ni kweli. Kwa mfano: + +```go +andika(kweli || sikweli) // Tokeo: `kweli` + +andika(sikweli || sikweli) // Tokeo: `sikweli` +``` + +### Kitendakazi `!` + +Kitendakazi `!` hukanusha thamani ya kitu. Kwa mfano: + +```go +andika(!kweli) // Tokeo: `sikweli` + +andika(!sikweli) // Tokeo: `kweli` +``` + +## Kufanya Kazi na Thamani za Buliani Katika Vitanzi + +Katika Nuru, unaweza ukatumia semi za buliani katika vitanzi kuendesha tabia zake. Kwa mfano: + +```go +namba = [1, 2, 3, 4, 5] + +kwa thamani ktk namba { + kama (thamani % 2 == 0) { + andika(thamani, " ni namba shufwa") + } sivyo { + andika(thamani, " ni namba witiri") + } +} + +// Output: +// 1 ni namba witiri +// 2 ni namba shufwa +// 3 ni namba witiri +// 4 ni namba shufwa +// 5 ni namba witiri +``` + +Hapa , tumetengeneza safu yenye namba 1 hadi 5 kisha tukazunguka ndani ya safu hiyo na kwa kila namba tukatumia kitendakazi `%` ilikubaini kama namba ni shufwa au witiri. Matokeo yatakua ni "ni namba shufwa" kwa namba shufwa na "ni namba witiri" kwa namba witiri. + +Vitu buliani katika Nuru vinaweza kutumika kutathmini semi ambazo zinarudisha thamani ya kweli au sikweli. Unaweza kutumia vitendakazi vya buliani kutathmini semi tata na kuendesha tabia ya vitanzi. Kuelewa namna ya kufanya kazi na thamani za buliani ni ujuzi wamsingi kwa mtengenezaji programu yeyote wa Nuru. diff --git a/repl/docs/sw/builtins.md b/repl/docs/sw/builtins.md index f807886..b4c188a 100644 --- a/repl/docs/sw/builtins.md +++ b/repl/docs/sw/builtins.md @@ -1 +1,54 @@ -# Builtins \ No newline at end of file +# Vitendakazi Vilivyojengwa Ndani ya Nuru + +Nuru ina vitendakazi kadhaa vilivyojengwa ndani vinavyofanya kazi husika. + +## Kitendakazi andika() + +Kitendakazi `andika()` kinatumika kuchapisha ujumbe kwenye konsoli. Inawezakuchukua hoja sifuri au zaidi, na hoja zitachapishwa na nafasi kati yao. Kwa kuongeza, `andika()` huhimili uundaji wa msingi kama vile `/n` kwa ajili ya mstari mpya, `/t` kwa ajili ya nafasi ya kichupo, na `\\` kwa ajili ya mkwajunyuma. Mfano: + +```go +andika(1, 2, 3) // Output: 1 2 3 +``` + +```go +andika("Jina: Asha /n Umri: 20 /n Chuo: IFM") + +// Output: +// Jina: Asha +// Umri: 20 +// Chuo: IFM +``` + +## Kitendakazi jaza() + +Kitendakazi `jaza()` kinatumika kupata ingizo kutoka kwa mtumiaji. Inawezakuchukua hoja sifuri au moja, ambayo ni utungo utakao tumika kama kimahasishi kwa mtumiaji. Mfano: + +```go +fanya salamu = unda() { + fanya jina = jaza("Unaitwa nani? ") + andika("Mambo vipi", jina) +} + +salamu() +``` + +Katika mfano huu, tunaainisha kitendakazi `salamu()` ambacho kinamhamasisha mtumiaji kuingiza jina kwa kutumia kitendakazi `jaza()`. Kisha tunatumia kitendakazi `andika()` kuchapisha ujumbe unaobeba jina la mtumiaji aliloingiza. + +## Kitendakazi aina() + +Kitendakazi `aina()` kinatumika kutambua aina ya kitu. Inakubali hoja moja, na thamani inayorudi hua ni utungo unaoonyesha aina ya kitu. Mfano: + +```go +aina(2) // Output: "NAMBA" +aina("Nuru") // Output: "NENO" +``` + +## Kitendakazi fungua() + +Kitendakazi `fungua()` kinatumika kufungua faili. Inakubali hoja moja, ambayo ni njia ya faili unalotaka kufungua. Mfano: + +```go +faili = fungua("data.txt") +``` + +Katika mfano huu, tumetumia kitendakazi `fungua()` kufungua faili linaloitwa "data.txt". Kibadilika `faili` kinabeba kumbukumbu ya faili lililofunguliwa. diff --git a/repl/docs/sw/dictionaries.md b/repl/docs/sw/dictionaries.md index 469ad6d..04f2762 100644 --- a/repl/docs/sw/dictionaries.md +++ b/repl/docs/sw/dictionaries.md @@ -1 +1,134 @@ -# Kamusi (Dictionaries) \ No newline at end of file +# Kamusi Katika Nuru + +Kamusi katika Nuru ni miundo ya data inayotunza jozi za funguo-thamani. Ukurasa huu unatoa maelezo kuhusu Kamusi katika Nuru, ikiwemo namna ya kutengeneza, namna ya kubadilisha, na namna ya kuzunguka ndani yake. + +## Kutengeneza Kamusi + +Kamusi zinawekwa kwenye mabano singasinga na hujumuisha funguo na thamani zake zikitenganishwa na nukta pacha. Mfano wa uainishwaji wa kamusi: + +```go + +orodha = {"jina": "Juma", "umri": 25} +``` + +Funguo zinawezakua tungo, namba, desimali, au buliani na thamani inaweza kua aina ya data yoyote ikiwemo tungo, namba, desimali, buliani, tupu, au kitendakazi: + +```go +k = { + "jina": "Juma", + "umri": 25, + kweli: "kweli", + "salimu": unda(x) { andika("habari", x) }, + "sina thamani": tupu +} +``` + +## Kupata Vipengele + +Unaweza kupata vipengele vya kamusi kwa kutumia funguo zake: + +```go +k = { + "jina": "Juma", + "umri": 25, + kweli: "kweli", + "salimu": unda(x) { andika("habari", x) }, + "sina thamani": tupu +} + +andika(k[kweli]) // kweli +andika(k["salimu"]("Juma")) // habari Juma +``` + +## Kuboresha Vipengele + +Boresha thamani ya kipengele kwa kukipa thamani mpya kwenye funguo yake: + +```go +k = { + "jina": "Juma", + "umri": 25, + kweli: "kweli", + "salimu": unda(x) { andika("habari", x) }, + "sina thamani": tupu +} + +k['umri'] = 30 +andika(k['umri']) // 30 +``` + +## Kuongeza Vipengele Vipya + +Ongeza jozi mpya ya funguo-thamani kwenye kamusi kwa kuipa thamani funguo ambayo haipo kwenye kamusi husika: + +```go +k["lugha"] = "Kiswahili" +andika(k["lugha"]) // Kiswahili +``` + +## Kuunganisha Kamusi + +Unganisha kamusi mbili kwa kutumia kiendeshi `+`: + +```go +matunda = {"a": "apple", "b": "banana"} +mboga = {"c": "tembele", "d": "mchicha"} +vyakula = matunda + mboga +andika(vyakula) // {"a": "apple", "b": "banana", "c": "tembele", "d": "mchicha"} +``` + +## Angalia Kama Funguo Ipo Kwenye Kamusi + +Tumia neno msingi `ktk` kuangalia kama funguo ipo kwenye kamusi: + +```go + +k = { + "jina": "Juma", + "umri": 25, + kweli: "kweli", + "salimu": unda(x) { andika("habari", x) }, + "sina thamani": tupu +} + +"umri" ktk k // kweli +"urefu" ktk k // sikweli +``` + +## Kuzunguka Ndani Ya Kamusi + +Zunguka ndani ya kamusi kupata funguo na thamani zake: + +```go + +hobby = {"a": "kulala", "b": "kucheza mpira", "c": "kuimba"} + +kwa i, v ktk hobby { + andika(i, "=>", v) +} + +//Output + +a => kulala +b => kucheza mpira +c => kuimba +``` + +Kuzunguka ndani ya kamusi na kupata thamani peke yake: + +```go + +hobby = {"a": "kulala", "b": "kucheza mpira", "c": "kuimba"} + +kwa i, v ktk hobby { + andika(i, "=>", v) +} + +//Output + +kulala +kucheza mpira +kuimba +``` + +Kwa ufahamu huu, unaweza ukatumia kamusi kikamilifu katika Nuru kutunza na kusimamia jozi za funguo-thamani, na kupata namna nyumbufu ya kupangilia na kupata data katika programu zako. diff --git a/repl/docs/sw/for.md b/repl/docs/sw/for.md index 52b9109..7883698 100644 --- a/repl/docs/sw/for.md +++ b/repl/docs/sw/for.md @@ -1 +1,166 @@ -# Kwa (For) \ No newline at end of file +# Vitanzi Vya Kwa Katika Nuru + +Vitanzi vya `kwa` ni muundo msingi wa udhibiti katika Nuru ambavyo hutumika kuzunguka vitu vinavyozungukika kama tungo, safu, na kamusi. Ukurasahuu unaangazia sintaksia na matumizi ya Vitanzi katika Nuru, ikiwemo kuzunguka ndani ya jozi ya funguo-thamani, na matumizi ya matamshi `vunja` na `endelea`. + +## Sintaksia + +Kutengeneza kitanzi cha `kwa`, tumia neno msingi `kwa` likifwatiwa na kitambulishi cha muda mfupi kama vile `i` au `v` na kitu kinachozungukika. Funga mwili wa kitanzi na mabano singasinga `{}`. Mfano unaotumia tungo: + +```go +jina = "lugano" + +kwa i ktk jina { + andika(i) +} + +// Tokeo: +l +u +g +a +n +o +``` + +## Kuzunguka Ndani ya Jozi ya Funguo-Thamani + +### Kamusi + +Nuru inakuruhusu kuzunguka ndani ya kamusi kupata thamani moja moja au jozi ya funguo na thamani yake. Kupata tu thamani, tumia kitambulisha cha muda mfupi: + +```go +kamusi = {"a": "andaa", "b": "baba"} + +kwa v ktk kamusi { + andika(v) +} + +// Tokeo: + +andaa +baba +``` + +Kupata thamani ya funguo na thamani zake, tumia vitambulishi vya muda mfupi viwili: + +```go + +kwa k, v ktk kamusi { + andika(k + " ni " + v) +} + +// Tokeo: + +a ni andaa +b ni baba +``` + +### Tungo + +Kuzunguka juu ya thamani za tungo, tumia kitambulishi cha muda mfupi: + +```go +kwa v ktk "mojo" { + andika(v) +} + +// Tokeo: + +m +o +j +o +``` + +Kuzunguka juu ya funguo na thamani zake, tumia vitambulishi vya muda mfupi viwili: + +```go +kwa i, v ktk "mojo" { + andika(i, "->", v) +} + +// Tokeo: + +0 -> m +1 -> o +2 -> j +3 -> o +``` + +### Safu + +Kuzunguka juu ya thamani za safu, tumia kitambulishi cha muda mfupi: + +```go +majina = ["juma", "asha", "haruna"] + +kwa v ktk majina { + andika(v) +} + +// Tokeo: + +juma +asha +haruna +``` + +Kuzunguka juu ya funguo na thamani katika safy, tumia vitambulishi vya muda mfupi viwili: + +```go +kwa i, v ktk majina { + andika(i, "-", v) +} + +// Tokeo: + +0 - juma +1 - asha +2 - haruna +``` + +## Vunja na Endelea + +### Vunja + +Tumia neno msingi `vunja` kisitisha kitanzi: + +```go + +kwa i, v ktk "mojo" { + kama (i == 2) { + andika("nimevunja") + vunja + } + andika(v) +} + +// Tokeo: + +m +o +j +nimevunja + +``` + +### Endelea + +Tumia neno msingi `endelea` kuruka mzunguko maalum: + +```go +kwa i, v ktk "mojo" { + kama (i == 2) { + andika("nimeruka") + endelea + } + andika(v) +} + +// Tokeo: + +m +o +nimeruka +o +``` diff --git a/repl/docs/sw/functions.md b/repl/docs/sw/functions.md index ed2c3d8..d913a52 100644 --- a/repl/docs/sw/functions.md +++ b/repl/docs/sw/functions.md @@ -1 +1,91 @@ -# Undo (Functions) \ No newline at end of file +# Undo (Functions) + +Vitendakazi ni sehemu ya msingi ya Nuru inayokuwezesha kuainisha mapande ya msimbo yanayoweza kutumika tena. Ukurasa huu unaainisha sintaksia na matumizi ya vitendakazi katika nuru ikiwemo vipengele, vipengele vya msingi, matamshi ya kurudisha, kujirudia, na vifungizi. + +## Sintaksia + +Pande la kitendakazi huanza na neno msingi `unda` likifuatiwa na vipengele vinavyowekwa ndani ya mabano `()` na mwili unaowekwa ndani ya mabano singasinga `{}`. Vitendakazi lazima viwekwe kwenye kibadiliki: + +```go +jumla = unda(x, y) { + rudisha x + y +} + +jumla(2, 3) // 5 +``` + +## Vipengele + +Vitendakazi vinawezakuwa nazifuri au idadi yoyote ya vipengele. Vipengele vinawezakua vya aina yoyote hata vitendakazi vingine: + +```go +salamu = unda(jina) { + andika("Habari yako", jina) +} + +salamu("asha") // Habari yako asha +``` + +## Vipengele Vya Msingi + +Vitendakazi vinawezakupewa vipengele vya msingi: + +```go +salimu = unda(salamu="Habari") { + andika(salamu) +} + +salimu() // Habari +salimu("Mambo") // Mambo +``` + +## Rudisha + +Unaweza pia ukarudisha thamani kwa kutumia neno msingi `rudisha`. Neno msingi `rudisha` husitisha pande la msimbo na kurudisha thamani: + +```go +mfano = unda(x) { + rudisha "nimerudi" + andika(x) +} + +mfano("x") // nimerudi +``` + +## Kujirudia + +Nuru pia inahimili kujirudia. Mfano wa kujirudia kwa kitendakazi cha Fibonacci: + +```go + +fib = unda(n) { + kama (n <= 1) { + rudisha n + } sivyo { + rudisha fib(n-1) + fib(n-2) + } +} + +andika(fib(10)) // 55 +``` + +Kitendakazi fib kinakokotoa namba ya Fibonacci ya n kwa kujiita yenyewe ikiwa na n-1 na n-2 kama vipengele mpaka ambapo n ni ndogo kuliko au sawa na moja. + +## Vifungizi + +Vifungizi ni vitendakazi visivyo na jina ambayo vinaweza kudaka na kuhifadhi marejeo ya vibadilika kutoka katika muktadha unaovizunguka. Katika Nuru, unaweza kutengeneza vifungizi kwa kutumia neno msingin `unda` bila kuiweka kwenye kibadiliki. Mfano: + +```go +fanya jum = unda(x) { + rudisha unda(y) { + rudisha x + y + } +} + +fanya jum_x = jum(5) +andika(jum_x(3)) // 8 +``` + +Katika mfano hapo juu, kitendakazi `jum` kinarudisha kitendakazi kingine ambacho kinabeba kipengele kimoja tu `y`. Kitendakazi kinachorudisha kinawezakupata kibadiliki x kutoka katika muktadha unaokizunguka. + +Sasa umeshaelewa misingi ya vitendakazi katika Nuru, ikiwemo kujirudia na vifungizi, unaweza ukatengeneza mapande ya msimbo yanayoweza kutumika tena na tena na kurahisisha programu zako na kuboresha mpangilio wa msimbo wako. diff --git a/repl/docs/sw/identifiers.md b/repl/docs/sw/identifiers.md index d89ef81..6dd592b 100644 --- a/repl/docs/sw/identifiers.md +++ b/repl/docs/sw/identifiers.md @@ -1 +1,32 @@ -# Tambulishi (Identifiers) \ No newline at end of file +# Vitambulisho katika Nuru + +Vitambulisho hutumika kuweka majina kwenye vigezo, vitendakazi na vipengele vingine katika msimbo wako wa Nuru. Ukurasa huu unashughulikia sheria na mbinu bora za kuunda vitambulisho katika Nuru. + +## Sheria za Sintaksia + +Vitambulisho vinaweza kuwa na herufi, nambari na nistari wa chini `_`. Walakini, kuna sheria chache ambazo unapaswa kufuata wakati wa kuunda vitambulisho: + +- Vitambulisho haviwezi kuanza na nambari. +- Vitambulisho huwa na tofauti kulingana na matumizi ya herufi kubwa na ndogo. Kwa mfano, `kibadilikaChangu` na `kibadilikachangu` huchukuliwa kuwa vitambulisho tofauti. + +Hapa kuna mifano ya vitambulisho halali: + +```go +fanya mwaka_wa_kuzaliwa = 2020 +andika(mwaka_wa_kuzaliwa) // 2020 + +fanya badili_c_kwenda_p = "C kwenda P" +andika(badili_c_kwenda_p) // "C kwenda P" +``` + +Katika mifano iliyo hapo juu, mwaka_wa_kuzaliwa na badili_c_kwenda_p zote ni vitambulisho halali. + +## Mazoea Bora + +Wakati wa kuchagua vitambulisho, ni muhimu kufuata mazoea bora ili kuhakikisha kuwa msimbo wako uko wazi na rahisi kueleweka: + +- Tumia majina yanayoelezea wazi kusudi au maana ya kigezo au kitendakazi. +- Fuata kanuni thabiti ya kuweka majina, kama vile camelCase (kibadilikaChangu) au snake_case (kibadilika_changu). +- Epuka kutumia majina tofauti ya herufi moja, isipokuwa kwa vijisehemu vinavyokubalika kwa kawaida kama vile vihesabu vitanzi (i, j, k). + +Kwa kufuata mbinu bora hizi unapounda vitambulisho, utafanya code yako ya Nuru iwe rahisi kusoma na kutunza kwa wewe na wengine. diff --git a/repl/docs/sw/comments.md b/repl/docs/sw/maoni.md similarity index 100% rename from repl/docs/sw/comments.md rename to repl/docs/sw/maoni.md diff --git a/repl/docs/sw/range.md b/repl/docs/sw/range.md new file mode 100644 index 0000000..d8e73c3 --- /dev/null +++ b/repl/docs/sw/range.md @@ -0,0 +1,55 @@ +## Kitendakazi cha Mfululizo + +Kitendakazi cha `mfululizo` hutoa mfululizo wa nambari, sawa na kitendakazi cha `range()` cha Python. Kinaweza kutumika katika vitanzi au kuunda safu za nambari zinazofuatana. + +### Muundo + +```go +mfululizo(mwisho) +mfululizo(mwanzo, mwisho) +mfululizo(mwanzo, mwisho, hatua) +``` + +### Vipengele + +- `mwisho`: Kikomo cha juu cha mfululizo (haijumuishwi). +- `mwanzo` (si lazima): Thamani ya kuanzia ya mfululizo. Chaguo-msingi ni 0. +- `hatua` (si lazima): Ongezeko kati ya kila nambari katika mfululizo. Chaguo-msingi ni 1. + +### Thamani Inayorudishwa + +Hurudisha safu ya nambari kamili. + +### Mifano + +```go +// Toa nambari kutoka 0 hadi 4 +kwa i katika mfululizo(5) { + andika(i) +} +// Tokeo: 0 1 2 3 4 + +// Toa nambari kutoka 1 hadi 9 +kwa i katika mfululizo(1, 10) { + andika(i) +} +// Tokeo: 1 2 3 4 5 6 7 8 9 + +// Toa nambari shufwa kutoka 0 hadi 8 +kwa i katika mfululizo(0, 10, 2) { + andika(i) +} +// Tokeo: 0 2 4 6 8 + +// Toa nambari kwa mpangilio wa kurudi nyuma +kwa i katika mfululizo(10, 0, -1) { + andika(i) +} +// Tokeo: 10 9 8 7 6 5 4 3 2 1 +``` + +### Vidokezo + +- Thamani ya `mwisho` haijumuishwi, ikimaanisha mfululizo utasimama kabla ya kufikia thamani hii. +- Ikiwa `hatua` hasi imetolewa, `mwanzo` inapaswa kuwa kubwa kuliko `mwisho`. +- Thamani ya `hatua` haiwezi kuwa sifuri. diff --git a/repl/repl.go b/repl/repl.go index 3af10ed..e9c73c0 100644 --- a/repl/repl.go +++ b/repl/repl.go @@ -8,11 +8,11 @@ import ( "strings" prompt "github.com/AvicennaJr/GoPrompt" - "github.com/AvicennaJr/Nuru/evaluator" - "github.com/AvicennaJr/Nuru/lexer" - "github.com/AvicennaJr/Nuru/object" - "github.com/AvicennaJr/Nuru/parser" - "github.com/AvicennaJr/Nuru/styles" + "github.com/NuruProgramming/Nuru/evaluator" + "github.com/NuruProgramming/Nuru/lexer" + "github.com/NuruProgramming/Nuru/object" + "github.com/NuruProgramming/Nuru/parser" + "github.com/NuruProgramming/Nuru/styles" "github.com/charmbracelet/bubbles/list" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" @@ -20,31 +20,6 @@ import ( ) const PROMPT = ">>> " -const ERROR_FACE = ` - β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ - β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–€β–€β–€β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–€β–€β–€β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ - β–ˆβ–ˆβ–ˆβ–ˆβ–€β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–€β–ˆβ–ˆβ–ˆβ–ˆ - β–ˆβ–ˆβ–ˆβ”‚β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β”‚β–ˆβ–ˆβ–ˆ - β–ˆβ–ˆβ–Œβ”‚β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β”‚β–β–ˆβ–ˆ - β–ˆβ–ˆβ–‘β””β”β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β”Œβ”˜β–‘β–ˆβ–ˆ - β–ˆβ–ˆβ–‘β–‘β””β”β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β”Œβ”˜β–‘β–‘β–ˆβ–ˆ - β–ˆβ–ˆβ–‘β–‘β”Œβ”˜β–„β–„β–„β–„β–„β–‘β–‘β–‘β–‘β–‘β–„β–„β–„β–„β–„β””β”β–‘β–‘β–ˆβ–ˆ - β–ˆβ–ˆβ–Œβ–‘β”‚β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–Œβ–‘β–‘β–‘β–β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ”‚β–‘β–β–ˆβ–ˆ - β–ˆβ–ˆβ–ˆβ–‘β”‚β–β–ˆβ–ˆβ–ˆβ–€β–€β–‘β–‘β–„β–‘β–‘β–€β–€β–ˆβ–ˆβ–ˆβ–Œβ”‚β–‘β–ˆβ–ˆβ–ˆ - β–ˆβ–ˆβ–€β”€β”˜β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–β–ˆβ–Œβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β””β”€β–€β–ˆβ–ˆ - β–ˆβ–ˆβ–„β–‘β–‘β–‘β–„β–„β–„β–“β–‘β–‘β–€β–ˆβ–€β–‘β–‘β–“β–„β–„β–„β–‘β–‘β–‘β–„β–ˆβ–ˆ - β–ˆβ–ˆβ–ˆβ–ˆβ–„β”€β”˜β–ˆβ–ˆβ–Œβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–β–ˆβ–ˆβ””β”€β–„β–ˆβ–ˆβ–ˆβ–ˆ - β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–β–ˆβ”€β”¬β”¬β”¬β”¬β”¬β”¬β”¬β”€β–ˆβ–Œβ–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆ - β–ˆβ–ˆβ–ˆβ–ˆβ–Œβ–‘β–‘β–‘β–€β”¬β”Όβ”Όβ”Όβ”Όβ”Όβ”Όβ”Όβ”¬β–€β–‘β–‘β–‘β–β–ˆβ–ˆβ–ˆβ–ˆ - β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–„β–‘β–‘β–‘β””β”΄β”΄β”΄β”΄β”΄β”΄β”΄β”˜β–‘β–‘β–‘β–„β–ˆβ–ˆβ–ˆβ–ˆβ–ˆ - β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–„β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–„β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ - β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–„β–„β–„β–„β–„β–„β–„β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ - β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ - - β–ˆβ–„β–€β€ƒβ–ˆβ–‘β–ˆβ€ƒβ–ˆβ–„β–‘β–ˆβ€ƒβ–„β–€β–ˆβ€ƒ β€ƒβ–ˆβ–€β€ƒβ–ˆβ–‘β–ˆβ€ƒβ–ˆβ€ƒβ–ˆβ–€β–„β€ƒβ–„β–€β–ˆ - β–ˆβ–‘β–ˆβ€ƒβ–ˆβ–„β–ˆβ€ƒβ–ˆβ–‘β–€β–ˆβ€ƒβ–ˆβ–€β–ˆβ€ƒ β€ƒβ–„β–ˆβ€ƒβ–ˆβ–€β–ˆβ€ƒβ–ˆβ€ƒβ–ˆβ–„β–€β€ƒβ–ˆβ–€β–ˆ - -` //go:embed docs var res embed.FS @@ -58,7 +33,6 @@ func Read(contents string) { program := p.ParseProgram() if len(p.Errors()) != 0 { - fmt.Println(styles.ErrorStyle.Italic(false).Render(ERROR_FACE)) fmt.Println(styles.ErrorStyle.Italic(false).Render("Kuna Errors Zifuatazo:")) for _, msg := range p.Errors() { @@ -174,6 +148,23 @@ var ( } kiswahiliItems = []list.Item{ - item{title: "Maoni Katika Nuru", desc: "πŸ’¬ Toa mawazo yako na maoni (comments) katika Nuru", filename: "comments.md"}, + item{title: "Maoni Katika Nuru", desc: "πŸ’¬ Toa mawazo yako na maoni (comments) katika Nuru", filename: "maoni.md"}, + item{title: "Vitambulishi", desc: "πŸ”– Toa utambulisho wa kipekee kwa vigezo vyako katika Nuru", filename: "identifiers.md"}, + item{title: "Nambari", desc: "πŸ”’ Gundua uchawi wa nambari katika Nuru", filename: "numbers.md"}, + item{title: "Maneno", desc: "🎼 Tunga hadithi kwa kutumia maneno katika Nuru", filename: "strings.md"}, + item{title: "Kamusi", desc: "πŸ“š Fungua maarifa ya kamusi katika Nuru", filename: "dictionaries.md"}, + item{title: "Buliani", desc: "πŸ‘πŸ‘Ž Kuwa mtaalam wa ulimwengu wa 'if' na 'else' kwa kutumia bool", filename: "bools.md"}, + item{title: "Tupu", desc: "🌌 Kubali utupu na Null katika Nuru", filename: "null.md"}, + item{title: "Safu", desc: "πŸš€ Fungua nguvu za safu (arrays) katika Nuru", filename: "arrays.md"}, + item{title: "Kwa", desc: "πŸ”„ Rudia kama mtaalam kwa kutumia 'kwa' katika Nuru", filename: "for.md"}, + item{title: "Wakati", desc: "βŒ› Jifunze sanaa ya subira na vitanzi vya 'wakati' katika Nuru", filename: "while.md"}, + item{title: "Undo", desc: "πŸ”§ Unda kazi zenye nguvu katika Nuru", filename: "function.md"}, + item{title: "Badili", desc: "🧭 Elekeza hali ngumu kwa kutumia 'badili' katika Nuru", filename: "switch.md"}, + item{title: "Faili", desc: "πŸ’Ύ Shughulikia faili kwa urahisi katika Nuru", filename: "files.md"}, + item{title: "Muda", desc: "⏰ Simamia muda kwa urahisi katika Nuru", filename: "time.md"}, + item{title: "JSON", desc: "πŸ“„ Kuwa mtaalam wa sanaa ya JSON katika Nuru", filename: "json.md"}, + item{title: "Mtandao", desc: "🌐 Chunguza ulimwengu wa mitandao katika Nuru", filename: "net.md"}, + item{title: "Vifurushi", desc: "πŸ“¦ Tumia nguvu za vifurushi katika Nuru", filename: "packages.md"}, + item{title: "Vijenzi", desc: "πŸ’‘ Funua siri za kazi za kujengwa katika Nuru", filename: "builtins.md"}, } ) diff --git a/sh/install.sh b/sh/install.sh new file mode 100755 index 0000000..cd29522 --- /dev/null +++ b/sh/install.sh @@ -0,0 +1,173 @@ +#!/usr/bin/env sh + +# Hii ni skripti ya shell ili kusakinisha programu ya Nuru. +# Programu zinazohitajika: +# - curl/wget: Kupakua faili za 'tar' kutoka 'Github' +# - cp: Nakili faili kuenda mahali sahihi +# - jq: Kupata uhusiano kwenye fomati ya 'JSON' +# - tar: Kufungua faili za tar.gz + +set -e + +ARCH="$(uname -m)" +OSNAME="$(uname -s)" +PREFIX_PATH="/usr" +BIN="" +VERSION="latest" +RELEASE_URL="https://github.com/NuruProgramming/Nuru/releases" +TEMP="" + +# Cleanup function to remove temp directory on exit +cleanup() { + if [ -n "$TEMP" ] && [ -d "$TEMP" ]; then + rm -rf "$TEMP" + fi +} +trap cleanup EXIT + +# Check if command exists +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +# Print usage information +usage() { + echo "Usage: $0 [OPTIONS]" + echo "" + echo "Options:" + echo " -p, --prefix The base path to be used when installing (default: /usr)" + echo " -v, --version The version to be downloaded from GitHub (default: latest)" + echo " -h, --help Show this help message" + echo "" +} + +# Normalize architecture names +arch_name() { + case "$ARCH" in + x86_64) + ARCH="amd64" + ;; + i386|i686) + ARCH="i386" + ;; + arm64|aarch64) + ARCH="arm64" + ;; + *) + echo "Unsupported architecture: $ARCH" + exit 2 + ;; + esac +} + +# Validate OS name +os_name() { + case "$OSNAME" in + Darwin|Linux|Android) + ;; + *) + echo "Unsupported Operating System: $OSNAME" + exit 2 + ;; + esac +} + +# Parse command line arguments +parse_args() { + while [ "$#" -gt 0 ]; do + case "$1" in + -h|--help) + usage + exit 0 + ;; + -p|--prefix) + shift + if [ -z "$1" ]; then + echo "Error: Missing argument for --prefix" + exit 1 + fi + PREFIX_PATH="$1" + ;; + -v|--version) + shift + if [ -z "$1" ]; then + echo "Error: Missing argument for --version" + exit 1 + fi + VERSION="$1" + ;; + --) + shift + break + ;; + *) + echo "Unknown argument: $1" + usage + exit 1 + ;; + esac + shift + done + BIN="$PREFIX_PATH/bin" +} + +# Download file using curl or wget +download() { + URL="$1" + if command_exists curl; then + curl -fSL "$URL" + elif command_exists wget; then + wget -qO- "$URL" + else + echo "Error: Neither curl nor wget is installed." + exit 1 + fi +} + +main() { + os_name + arch_name + parse_args "$@" + + # Check required commands + for cmd in jq tar cp; do + if ! command_exists "$cmd"; then + echo "Error: Required command '$cmd' not found." + exit 1 + fi + done + + if [ "$VERSION" = "latest" ]; then + echo "Fetching latest version tag from GitHub..." + VERSION="$(download "https://api.github.com/repos/NuruProgramming/Nuru/releases/latest" | jq -r .tag_name)" + if [ -z "$VERSION" ] || [ "$VERSION" = "null" ]; then + echo "Error: Unable to determine latest version." + exit 1 + fi + fi + + TAR_URL="$RELEASE_URL/download/$VERSION/nuru_${OSNAME}_${ARCH}.tar.gz" + echo "Downloading Nuru version $VERSION for $OSNAME/$ARCH..." + + TEMP="$(mktemp -d)" + if ! download "$TAR_URL" | tar -xz -C "$TEMP"; then + echo "Error: Failed to download or extract archive." + exit 1 + fi + + # Ensure bin directory exists + if [ ! -d "$BIN" ]; then + echo "Creating directory $BIN" + mkdir -p "$BIN" + fi + + echo "Installing Nuru to $BIN/nuru" + if ! cp "$TEMP/nuru" "$BIN/"; then + echo "Error: Failed to copy binary to $BIN" + exit 1 + fi + + echo "Installation complete." +} + +main "$@" diff --git a/third_party/math/README.md b/third_party/math/README.md new file mode 100644 index 0000000..08a2e38 --- /dev/null +++ b/third_party/math/README.md @@ -0,0 +1,253 @@ +# Pakeji Hesabu (Math Package) + +Pakeji Hesabu is a math package written in pure Nuru by [VictorKariuki](https://github.com/VictorKariuki). + +This package provides various mathematical functions and constants implemented in nuru programming language. It includes methods for `trigonometric functions`, `logarithmic functions`, `array operations`, and `utility functions`. + + +## Usage +To use the `pakeji hesabu` package follow the steps below: + +1. Copy the `hesabu.nr` file and any required third-party package files into the same directory as your project. + +2. Ensure that the package file names end with the `.nr` extension and match the package names. For example, if the package name is `hesabu`, the corresponding file name should be `hesabu.nr`. + +3. You can directly import the `hesabu.nr` package and any required third-party packages in your Nuru code using the `tumia` keyword. For example: + + ```nuru + tumia "hesabu" + ``` + Example of calling the package methods: + ```nuru + andika(hesabu.e()) +## What is in +This package covers a wide range of mathematical operations, including `basic arithmetic`, `trigonometry`, `exponential and logarithmic functions`, `rounding and comparison operations`, as well as some `utility and array operations`. + +The methods provided in the `hesabu` package can be classified into different categories based on their functionalities. Here is a classification of the methods: + +1. Trigonometric Functions: + - `cos(x)` + - `sin(x)` + - `tan(x)` + - `acos(x)` + - `asin(x)` + - `atan(x)` + +2. Hyperbolic Functions: + - `cosh(x)` + - `sinh(x)` + - `tanh(x)` + - `acosh(x)` + - `asinh(x)` + - `atanh(x)` + +3. Exponential and Logarithmic Functions: + - `exp(x)` + - `expm1(x)` + - `log(x)` + - `log10(x)` + - `log1p(x)` + +4. Other Mathematical Functions: + - `abs(namba)` + - `ceil(x)` + - `floor(x)` + - `sqrt(x)` + - `cbrt(x)` + - `root(x, n)` + - `hypot(values)` + - `factorial(n)` + +5. Rounding and Comparison Functions: + - `round(x, method)` + - `max(numbers)` + - `min(numbers)` + +6. Utility Functions: + - `sign(x)` + - `isNegative(num)` + - `isInteger(num)` + - `getIntegerPart(num)` + +7. Array and List Operations: + - `list(first, last, interval)` + - `reduce(iterator, callback, initialValue)` + + +### 1. Constants: + - **PI**: Represents the mathematical constant `Ο€`. + - **e**: Represents `Euler's Number`. + - **phi**: Represents the `Golden Ratio`. + - **ln10**: Represents the `natural logarithm of 10`. + - **ln2**: Represents the `natural logarithm of 2`. + - **log10e**: Represents the `base 10 logarithms` of Euler's number `(e)`. + - **log2e**: Represents the `base 2 logarithm` of Euler's number` (e)`. + - **sqrt1_2**: Represents the `square root` of `1/2`. + - **sqrt2**: Represents the `square root` of `2`. + - **sqrt3**: Represents the `square root` of `3`. + - **sqrt5**: Represents the `square root` of `5`. + - **EPSILON**: Represents a small value (2.220446049250313e-16). + +### 2. Methods: + +1. **abs(namba)** + - Description: Calculates the absolute value of a number. + - Example: `hesabu.abs(-42)` returns `42`. + +2. **acos(x)** + - Description: Calculates the arccosine of a number. + - Example: `hesabu.acos(0.5)` returns `1.0471975511965979`. + +3. **acosh(x)** + - Description: Calculates the inverse hyperbolic cosine of a number. + - Example: `hesabu.acosh(2)` returns `1.3169578969248166`. + +4. **asin(x)** + - Description: Calculates the arcsine of a number using the Taylor series. + - Example: `hesabu.arcsin(0.5)` returns `0.5235987755982989`. + +5. **asinh(x)** + - Description: Calculates the inverse hyperbolic sine of a number. + - Example: `hesabu.arsinh(2)` returns `1.4436354751788103`. + +6. **atan(x)** + - Description: Calculates the arctangent of a number using the Taylor series. + - Example: `hesabu.atan(1)` returns `0.7853981633974485`. + +7. **atan2(y, x)** + - Description: Calculates the arctangent of the quotient of its arguments. + - Example: `hesabu.atan2(1, 1)` returns `0.7853981633974483`. + +8. **atanh(x)** + - Description: Calculates the inverse hyperbolic tangent of a number. + - Example: `hesabu.atanh(0.5)` returns `0.5493061443340549`. + +9. **cbrt(x)** + - Description: Calculates the cube root of a number. + - Example: `hesabu.cbrt(8)` returns `2`. + +10. **root(x, n)** + - Description: Calculates the nth root of a number using the Newton-Raphson method. + - Example: `hesabu.root(27, 3)` returns `3`. + +11. **ceil(x)** + - Description: Rounds up to the smallest integer greater than or equal to a given number. + - Example: `hesabu.ceil(4.3)` returns `5`. + +12. **cos(x)** + - Description: Calculates the cosine of an angle in radians using the Taylor series. + - Example: `hesabu.cos(5)` returns `0.28366218546322464`. + +13. **cosh(x)** + - Description: Calculates the hyperbolic cosine of a number. + - Example: `hesabu.cosh(5)` returns `74.20994842490012`. + +14. **exp(x)** + - Description: Calculates the value of Euler's number raised to the power of a given number. + - Example: `hesabu.exp(2)` returns `7.389056098930649`. + +15. **expm1(x)** + - Description: Calculates Euler's number raised to the power of a number minus 1. + - Example: `hesabu.expm1(1)` returns `1.7182818284590455`. + +16. **floor(x)** + - Description: Rounds down to the largest integer less than or equal to a given number. + - Example: `hesabu.floor(4.7)` returns `4`. + +17. **hypot(values)** + - Description: Calculates the square root of the sum of squares of the given values. + - Example: `hesabu.hypot([3, 4])` returns `5`. + +18. **log(x)** + - Description: Calculates the natural logarithm of a number. + - Example: `hesabu.log(2)` returns `0.69314718056`. + +19. **log10(x)** + - Description: Calculates the base 10 logarithm of a number. + - Example: `hesabu.log10(100)` returns `1.9999999999573126`. + +20. **log1p(x)** + - Description: Calculates the natural logarithm of 1 plus the given number. + - Example: `hesabu.log1p(1)` returns `0.6931471805599451`. + +21. **log2(x)** + - Description: Calculates the base 2 logarithm of a number. + - Example: `hesabu.log2(8)` returns `3`. + +22. **max(numbers)** + - Description: Finds the maximum value in a list of numbers. + - Example: `hesabu.max([4, 2, 9, 5])` returns `9`. + +23. **min(numbers)** + - Description: Finds the minimum value in a list of numbers. + - Example: `hesabu.min([4, 2, 9, 5])` returns `2`. + +24. **round(x, method)** + - Description: Rounds a number to the nearest integer using the specified method. + - supported methods: + - "rpi" (round to the nearest integer using the principle of rounding half to the nearest even) + - "rni" (round to the nearest integer using the principle of rounding half away from zero) + - "ri" (round to the nearest integer using the standard rounding method) + - An invalid method results in returning NaN (Not a Number) + - Example: `hesabu.round(4.6, "rpi")` returns `5`. + +25. **sign(x)** + - Description: Determines the sign of a number. + - Example: `hesabu.sign(-5)` returns `-1`. + +26. **sin(x)** + - Description: Calculates the sine of an angle in radians using the Taylor series. + - Example: `hesabu.sin(1)` returns `0.8414709848078965`. + +27. **sinh(x)** + - Description: Calculates the hyperbolic sine of a number. + - Example: `hesabu.sinh(0)` returns `0`. + +28. **sqrt(x)** + - Description: Calculates the square root of a number. + - Example: `hesabu.sqrt(4)` returns `2`. + +29. **tan(x)** + - Description: Calculates the tangent of an angle in radians. + - Example: `hesabu.tan(1)` returns `1.557407724654902`. + +30. **tanh(x)** + - Description: Calculates the hyperbolic tangent of a number. + - Example: `hesabu.tanh(0)` returns `0`. + +31. **factorial(n)** + - Description: Calculates the factorial of a number. + - Example: `hesabu.factorial(5)` returns `120`. + +32. **isNegative(num)** + - Description: Checks if a number is negative. + - Example: `hesabu.isNegative(-5)` returns `kweli`. + +33. **isInteger(num)** + - Description: Checks if a number is an integer. + - Example: `hesabu.isInteger(4.5)` returns `sikweli`. + +34. **getIntegerPart(num)** + - Description: Gets the integer part of a number. + - Example: `hesabu.getIntegerPart(4.5)` returns `4`. + +35. **list(first, last, interval)** + - Description: Creates a list of numbers with the specified interval between them. + - Example: `hesabu.list(1, 5, 1)` returns `[1, 2, 3, 4]`. + +36. **reduce(iterator, callback, initialValue)** + - Description: Reduces the elements of an array to a single value using a specified callback function. + - Example: `hesabu.reduce([1, 2, 3, 4], [callback function], 0)` + ```s + fanya callback = unda(accumulator, currentValue){ + rudisha accumulator + currentValue; + } + + andika(hesabu.reduce([1, 2, 3, 4], callback, 0)) \\ returns 10. +### Contributing + +Contributions to the `pakeji hesabu` package are welcome. If you have any improvements or bug fixes, feel free to create a pull request. + +### License + +This package is available under the MIT License. See the [LICENSE](LICENSE) file for more information. \ No newline at end of file diff --git a/third_party/math/hesabu.nr b/third_party/math/hesabu.nr new file mode 100644 index 0000000..ec113c8 --- /dev/null +++ b/third_party/math/hesabu.nr @@ -0,0 +1,533 @@ +tumia hisabati + +pakeji hesabu{ + //CONSTRUCTOR METHOD + andaa = unda() {} + + // Constants + // Ο€ (Pi) + PI = unda() { + rudisha 3.141592653589793; + } + + // e (Euler's Number) + e = unda() { + rudisha 2.718281828459045; + } + + // Ο† (Phi, Golden Ratio) + phi = unda() { + rudisha 1.618033988749895; + } + + // Natural logarithm of 10 + ln10 = unda() { + rudisha 2.302585092994046; + } + + // Natural logarithm of 2 + ln2 = unda() { + rudisha 0.6931471805599453; + } + + // Base 10 logarithm of Euler's number (e) + log10e = unda() { + rudisha 0.4342944819032518; + } + + // Base 2 logarithm of Euler's number (e) + log2e = unda() { + rudisha 1.4426950408889634; + } + + // √1/2 (equivalent to 1 / sqrt(2)) + sqrt1_2 = unda() { + rudisha 0.7071067811865476; + } + + // √2 (Square Root of 2) + sqrt2 = unda() { + rudisha 1.414213562373095; + } + + // √3 (Square Root of 3) + sqrt3 = unda() { + rudisha 1.732050807568877; + } + + // √5 (Square Root of 5) + sqrt5 = unda() { + rudisha 2.236067977499790; + } + + // @.EPSILON + EPSILON = unda() { + rudisha 0.0000000000000002220446049250313; + } + + // Methods + //abs(namba), calculates the absolute value of a number. + abs = unda(namba){ + kama(namba < 0){ + rudisha - 1 * namba; + } + + rudisha namba; + } + + //acos(x), calculates the arccosine of a number. + acos = unda(x) { + kama (x < -1 || x > 1) { + rudisha "NaN"; + } + + fanya EPSILON = 1*10.0**-10; // Small value for precision + + fanya acosRecursive = unda(guess) { + fanya f = cos(guess) - x; + fanya fPrime = -sin(guess); + fanya nextGuess = guess - f / fPrime; + + kama (abs(nextGuess - guess) < EPSILON) { + rudisha nextGuess; + } + + rudisha acosRecursive(nextGuess); + } + + rudisha acosRecursive(hisabati.PI() / 2); // Initial guess for acos + } + + //acosh(x), calculates the inverse hyperbolic cosine of a number. + acosh = unda(x) { + kama(x < 1) { + rudisha 0; + } + + rudisha log(x + sqrt(x * x - 1)); + } + + //asin(x), calculates the arcsine of a number using the Newton Method. + asin = unda(x) { + kama (x < -1 || x > 1) { + rudisha "NaN"; + } + + fanya maxIterations = 50; // Maximum number of iterations + + fanya newtonAsin = unda(guess, prev, iterations) { + fanya next = guess - (sin(guess) - x) / cos(guess); + + kama (abs(next - prev) < hisabati.EPSILON() || iterations >= maxIterations) { + rudisha next; + } + + rudisha newtonAsin(next, guess, iterations + 1); + } + + rudisha newtonAsin(x, 1, 0); + } + + + //asinh(x), calculates the inverse hyperbolic sine of a number. + asinh = unda(x) { + // Calculate arsinh using the formula: arsinh(x) = ln(x + sqrt(x^2 + 1)) + kama(x >= 0) { + rudisha log(x + sqrt(x * x + 1)); + } sivyo { + // For negative values, arsinh(x) = -arsinh(-x) + rudisha - log(-x + sqrt(x * x + 1)); + } + } + + //atan(x), calculates the arctangent of a number using the Taylor series. + atan = unda(x) { + fanya EPSILON = 1*10.0**-10; // Small value for precision + + fanya atanRecursive = unda(guess) { + fanya f = tan(guess) - x; + fanya fPrime = 1 / (cos(guess) * cos(guess)); + fanya nextGuess = guess - f / fPrime; + + kama (abs(nextGuess - guess) < EPSILON) { + rudisha nextGuess; + } + + rudisha atanRecursive(nextGuess); + } + + rudisha atanRecursive(x); // Initial guess for atan + } + + //atanh(x), calculates the inverse hyperbolic tangent of a number. + atan2 = unda(y, x) { + kama(x > 0) { + rudisha atan(y / x); + } au kama(x < 0 && y >= 0) { + rudisha atan(y / x) + hisabati.PI(); + } au kama(x < 0 && y < 0) { + rudisha atan(y / x) - hisabati.PI(); + } au kama(x == 0 && y > 0) { + rudisha hisabati.PI() / 2; + } au kama(x == 0 && y < 0) { + rudisha - hisabati.PI() / 2; + } au kama(x == 0 && y == 0) { + rudisha "NaN"; // Undefined + } + } + + //atanh(x), calculates the inverse hyperbolic tangent of a number. + atanh = unda(x) { + kama(x < -1 || x > 1) { + rudisha 0; + } + rudisha 0.5 * log((1.0 + x) / (1.0 - x)); + } + + //cbrt(x), calculates the cube root of a number. + cbrt = unda(x) { + kama(x == 0) { + rudisha 0; + } + + kama(x >= 0) { + rudisha root(x, 3); + } sivyo { + rudisha - root(-x, 3); + } + } + + //root(x, n), calculates the nth root of a number using the Newton-Raphson method. + root = unda(x, n) { + fanya guess = x / 2; // Initial guess + fanya tolerance = 0.0000000001; // Tolerance for convergence + + fanya calculateNthRoot = unda(x, n, guess, tolerance) { + fanya nextGuess = ((n - 1) * guess + x / (guess ** (n - 1))) / n; + fanya ipotolerance = abs(nextGuess - guess); + kama (ipotolerance < tolerance) {rudisha nextGuess}; + rudisha calculateNthRoot(x, n, nextGuess, tolerance); + } + + rudisha calculateNthRoot(x, n, guess, tolerance) + } + + //ceil(x), rounds up to the smallest integer greater than or equal to a given number. + ceil = unda(x) { + kama(x >= 0) { + kama(x % 1 == 0) { + rudisha x; // x is already an integer + } + rudisha floor(x) + 1; + } sivyo { + rudisha - floor(abs(x)); + } + } + + //cos(x), calculates the cosine of an angle. + cos = unda(x) { + fanya result = 1; // Initialize the result + fanya term = 1; + + kwa i ktk list(2,101,2) { + term = (-term * x * x) / (i * (i - 1)); + result += term; + } + rudisha result; + } + + //cosh(x), calculates the hyperbolic cosine of a number. + cosh = unda(x) { + fanya eToX = exp(x); + fanya eToMinusX = exp(-x); + rudisha(eToX + eToMinusX) / 2; + } + + //exp(x), calculates the value of Euler's number raised to the power of a given number. + exp = unda(n) { + fanya result = 1; + fanya term = 1; + + kwa i, v ktk list(1,23,1) { + term = term*(n/v); + result = result + term; + } + + rudisha result; + } + + + //expm1(x), calculates the value of Euler's number raised to the power of a given number minus 1. + expm1 = unda(x) { + kama (x == -1) { + rudisha -0.6321205588285577; // Handling the special case for -1 + } au kama (x == 0) { + rudisha 0; // Handling the special case for 0 + } au kama (abs(x) < hisabati.EPSILON()) { + rudisha x + 0.5 * x * x; // Approximation for very small x + } sivyo { + rudisha exp(x) - 1; + } + } + + + //floor(x), rounds down to the largest integer less than or equal to a given number. + floor = unda(x) { + kama(x >= 0) { + rudisha x - (x % 1); + } sivyo { + rudisha x - (1 + x % 1); + } + } + + //hypot(values), calculates the square root of the sum of squares of the given values. + hypot = unda(values) { + // Calculate the sum of squares of the values + fanya exp = unda(acc, value){ + rudisha acc + value ** 2; + } + + fanya sumOfSquares = reduce(values, exp, 0); + + // Calculate the square root of the sum of squares + fanya result = sqrt(sumOfSquares); + + rudisha result; + } + + //log(x), calculates the natural logarithm of a number. + log = unda(x) { + kama (x <= 0) { + rudisha "NaN"; + } + kama (x == 1) { + rudisha 0; + } + kama (x < 0) { + rudisha -log(-x); + } + fanya n = 1000; // Number of iterations + fanya y = (x - 1) / (x + 1); + fanya ySquared = y * y; + fanya result = 0; + kwa i ktk list(1,n+1,2) { + result += (1 / i) * y**i; + } + rudisha 2 * result; + } + + //log10(x), calculates the base 10 logarithm of a number. + log10 = unda(x) { + kama(x <= 0) { + rudisha 0; + } + + // Calculate natural logarithm and divide by the natural logarithm of 10 + rudisha log(x) / log(10.0); + } + + //log1p(x), calculates the natural logarithm of 1 plus the given number. + log1p = unda(x) { + kama (x <= -1) { + rudisha NaN; // Not a Number + } au kama (abs(x) < hisabati.EPSILON()) { + rudisha x - 0.5 * x * x; // Series expansion for small x + } sivyo { + rudisha log(1.0 + x); + } + } + + //log2(x), calculates the base 2 logarithm of a number. + log2 = unda(x) { + kama(x <= 0) { + rudisha 0; + } + + fanya result = 0; + fanya currentValue = x; + + wakati(currentValue > 1) { + currentValue /= 2; + result++; + } + + rudisha result; + } + + //max(numbers), finds the maximum value in a list of numbers. + max = unda(numbers) { + // Initialize a variable to store the largest number + fanya largest = 0; + + // Iterate through the numbers and update 'largest' kama a larger number is found + kwa num ktk numbers { + kama(num > largest) { + largest = num; + } + } + + // rudisha the largest number (or 0 kama there are no parameters) + rudisha largest; + } + + //min(numbers), finds the minimum value in a list of numbers. + min = unda(numbers) { + kama(numbers.idadi() == 0) { + rudisha 0; + } + + fanya minVal = numbers[0]; + + fanya i = 1; + wakati(i < numbers.idadi()) { + kama(numbers[i] < minVal) { + minVal = numbers[i]; + } + i++; + } + + rudisha minVal; + } + + //round(x, method), rounds a number to the nearest integer using the specified method. + round = unda(x, method = "ri") { + kama(method == "rpi") { + rudisha floor(x + 0.5); + } au kama(method == "rni") { + rudisha ceiling(x - 0.5); + } au kama(method == "ri") { + kama(x >= 0){ + rudisha floor(x + 0.5); + }sivyo{ + rudisha ceiling(x - 0.5); + } + } sivyo { + rudisha NaN; // Invalid method + } + } + + //sign(x), determines the sign of a number. + sign = unda(x) { + kama(x == 0 || x == -0) { + rudisha x; + } au kama(x > 0) { + rudisha 1; + } sivyo { + rudisha - 1; + } + } + + //sin(x), calculates the sine of an angle in radians using the Taylor series. + sin = unda(x) { + fanya result = x; // Initialize the result with the angle + fanya term = x; + // Using Maclaurin series expansion for sine + kwa i ktk list(3,101,2) { + term = (-term * x * x) / (i * (i - 1)); + result += term; + } + rudisha result; + } + + //sinh(x), calculates the hyperbolic sine of a number. + sinh = unda(x) { + // sinh(x) = (e^x - e^(-x)) / 2 + fanya eToX = exp(x); + fanya eToMinusX = exp(-x); + rudisha(eToX - eToMinusX) / 2; + } + + //sqrt(x), calculates the square root of a number. + sqrt = unda(x) { + kama(x < 0) { + rudisha 0; + } + kama(x >= 0) { + rudisha root(x, 2); + } sivyo { + rudisha - root(-x, 2); + } + } + + //tan(x), calculates the tangent of an angle in radians. + tan = unda(x) { + fanya sineX = sin(x); + fanya cosineX = sqrt(1 - sineX * sineX); + + kama(cosineX == 0) { + rudisha 0; + } + + rudisha sineX / cosineX; + } + + //tanh(x), calculates the hyperbolic tangent of a number. + tanh = unda(x) { + fanya expX = exp(x); + fanya expNegX = exp(-x); + rudisha(expX - expNegX) / (expX + expNegX); + } + + // utility methods + //factorial(n), calculates the factorial of a number. + factorial = unda(n) { + kama(n == 0){ + rudisha 1; + }; + fanya result = 1; + fanya i = 1; + + wakati(i <= n) { + result *= i; + i++; + } + + rudisha result; + + } + + //isNegative(num), checks if a number is negative. + isNegative = unda(num) { + rudisha sign(num)==-1; + } + + //isInteger(num), checks if a number is an integer. + isInteger = unda(num) { + rudisha num == floor(num); + } + + //getIntegerPart(num), gets the integer part of a number. + getIntegerPart = unda(num) { + // Handle negative numbers separately + kama(isNegative(num)) { + // For negative numbers, we subtract the absolute value of the fractional part from 1 + rudisha - (ceil(-num) - 1); + } sivyo { + // For positive numbers, we simply truncate the fractional part + rudisha floor(num); + } + } + + //Arrray Methods + //list(first, last, interval), creates a list of numbers with the specified interval between theM. + list = unda(first, last, interval){ + fanya list = [first]; + fanya i = first + interval; + wakati(i < last){ + list.sukuma(i); + i += interval; + } + rudisha list; + } + + //reduce(iterator, callback, initialValue), reduces the elements of an array to a single value using a specified callback function. + reduce = unda(iterator, callback, initialValue) { + fanya accumulator = initialValue; + + kwa thamani ktk iterator { + accumulator = callback(accumulator, thamani); + } + + rudisha accumulator; + } +} diff --git a/third_party/math/test.nr b/third_party/math/test.nr new file mode 100644 index 0000000..29b9895 --- /dev/null +++ b/third_party/math/test.nr @@ -0,0 +1,41 @@ +tumia "hesabu" + +andika("abs: ",hesabu.abs(-42)); +andika("acos: ",hesabu.acos(0.5)); +andika("acosh: ",hesabu.acosh(2)); +andika("asin: ", hesabu.asin(0.5)); +andika("asinh: ",hesabu.asinh(2)); +andika("atan: ",hesabu.atan(1)); +andika("atan2: ",hesabu.atan2(1, 1)); +andika("atanh: ",hesabu.atanh(0.5)); +andika("cbrt: ",hesabu.cbrt(8)); +andika("root: ",hesabu.root(27, 3)); +andika("ceil: ",hesabu.ceil(4.3)); +andika("cos: ",hesabu.cos(5)); +andika("cosh: ",hesabu.cosh(5)); +andika("exp: ",hesabu.exp(2)); +andika("expm1: ",hesabu.expm1(1)); +andika("floor: ",hesabu.floor(4.7)); +andika("hypot: ",hesabu.hypot([3, 4])); +andika("log: ",hesabu.log(2)); +andika("log10: ",hesabu.log10(100)); +andika("log1p: ",hesabu.log1p(1)); +andika("log2: ",hesabu.log2(8)); +andika("max: ",hesabu.max([4, 2, 9, 5])); +andika("min: ",hesabu.min([4, 2, 9, 5])); +andika("round: ",hesabu.round(4.6, "rpi")); +andika("sign: ",hesabu.sign(-5)); +andika("sin: ",hesabu.sin(1)); +andika("sinh: ",hesabu.sinh(0)); +andika("sqrt: ",hesabu.sqrt(4)); +andika("tan: ",hesabu.tan(1)); +andika("tanh: ",hesabu.tanh(0)); +andika("factorial: ",hesabu.factorial(5)); +andika("isNegative: ",hesabu.isNegative(-5)); +andika("isInteger: ",hesabu.isInteger(4.5)); +andika("getIntegerPart: ",hesabu.getIntegerPart(4.5)); +andika("list: ",hesabu.list(1, 5, 1)); +fanya callback = unda(accumulator, currentValue){ + rudisha accumulator + currentValue; +} +andika("reduce: ",hesabu.reduce([1, 2, 3, 4],callback,0) ); diff --git a/token/token.go b/token/token.go index fff5b1d..18c4f6a 100644 --- a/token/token.go +++ b/token/token.go @@ -1,3 +1,5 @@ +// This is where we define our tokens + package token type TokenType string @@ -42,6 +44,7 @@ const ( ASTERISK_ASSIGN = "*=" SLASH_ASSIGN = "/=" MODULUS_ASSIGN = "%=" + SHEBANG = "#!" //Delimiters COMMA = ","