Full Code of AvicennaJr/Nuru for AI

main 78076bbdc2b5 cached
166 files
399.8 KB
125.8k tokens
654 symbols
1 requests
Download .txt
Showing preview only (436K chars total). Download the full file or copy to clipboard to get everything.
Repository: AvicennaJr/Nuru
Branch: main
Commit: 78076bbdc2b5
Files: 166
Total size: 399.8 KB

Directory structure:
gitextract_yf7p31zd/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.yml
│   │   └── feature-request.yml
│   ├── PULL_REQUEST_TEMPLATE
│   └── workflows/
│       ├── build.yml
│       └── tests.yml
├── .gitignore
├── .goreleaser.yaml
├── ABOUT.md
├── LICENSE
├── Makefile
├── README.md
├── ast/
│   ├── ast.go
│   └── ast_test.go
├── evaluator/
│   ├── assign.go
│   ├── assignEqual.go
│   ├── at.go
│   ├── bang.go
│   ├── block.go
│   ├── builtins.go
│   ├── builtins_common.go
│   ├── builtins_wasm.go
│   ├── call.go
│   ├── dict.go
│   ├── error_handler.go
│   ├── evaluator.go
│   ├── evaluator_test.go
│   ├── forin.go
│   ├── function.go
│   ├── identifier.go
│   ├── if.go
│   ├── import.go
│   ├── in.go
│   ├── index.go
│   ├── infix.go
│   ├── method.go
│   ├── package.go
│   ├── postfix.go
│   ├── prefix.go
│   ├── property.go
│   ├── switch.go
│   ├── type.go
│   └── while.go
├── examples/
│   ├── Astart.nr
│   ├── example.nr
│   ├── perceptron.nr
│   ├── reduce.nr
│   ├── sarufi.nr
│   ├── sorting_algorithm.nr
│   └── sudoku_solver.nr
├── extensions/
│   ├── README.md
│   ├── vim/
│   │   └── syntax/
│   │       └── nuru.vim
│   └── vscode/
│       ├── CHANGELOG.md
│       └── README.md
├── go.mod
├── go.sum
├── gotest
├── lexer/
│   ├── lexer.go
│   └── lexer_test.go
├── main.go
├── main_wasm.go
├── module/
│   ├── hisabati.go
│   ├── json.go
│   ├── module.go
│   ├── net.go
│   ├── os.go
│   └── time.go
├── object/
│   ├── array.go
│   ├── at.go
│   ├── bool.go
│   ├── break.go
│   ├── builtin.go
│   ├── byte.go
│   ├── continue.go
│   ├── dict.go
│   ├── environment.go
│   ├── error.go
│   ├── error_wasm.go
│   ├── file.go
│   ├── float.go
│   ├── function.go
│   ├── instance.go
│   ├── integer.go
│   ├── module.go
│   ├── null.go
│   ├── object.go
│   ├── object_test.go
│   ├── package.go
│   ├── return.go
│   ├── strings.go
│   └── time.go
├── parser/
│   ├── arrays.go
│   ├── assignEqual.go
│   ├── assignment.go
│   ├── at.go
│   ├── boolean.go
│   ├── break.go
│   ├── continue.go
│   ├── dict.go
│   ├── dot.go
│   ├── float.go
│   ├── for.go
│   ├── function.go
│   ├── identifier.go
│   ├── if.go
│   ├── import.go
│   ├── index.go
│   ├── integer.go
│   ├── null.go
│   ├── package.go
│   ├── parser.go
│   ├── parser_test.go
│   ├── statements.go
│   ├── string.go
│   ├── switch.go
│   └── while.go
├── repl/
│   ├── docs/
│   │   ├── en/
│   │   │   ├── README.md
│   │   │   ├── arrays.md
│   │   │   ├── bool.md
│   │   │   ├── builtins.md
│   │   │   ├── comments.md
│   │   │   ├── dictionaries.md
│   │   │   ├── files.md
│   │   │   ├── for.md
│   │   │   ├── function.md
│   │   │   ├── hisabati.md
│   │   │   ├── identifiers.md
│   │   │   ├── ifStatements.md
│   │   │   ├── json.md
│   │   │   ├── keywords.md
│   │   │   ├── net.md
│   │   │   ├── null.md
│   │   │   ├── numbers.md
│   │   │   ├── operators.md
│   │   │   ├── packages.md
│   │   │   ├── range.md
│   │   │   ├── strings.md
│   │   │   ├── switch.md
│   │   │   ├── time.md
│   │   │   └── while.md
│   │   └── sw/
│   │       ├── README.md
│   │       ├── arrays.md
│   │       ├── bools.md
│   │       ├── builtins.md
│   │       ├── dictionaries.md
│   │       ├── for.md
│   │       ├── functions.md
│   │       ├── identifiers.md
│   │       ├── if.md
│   │       ├── keywords.md
│   │       ├── maoni.md
│   │       ├── null.md
│   │       ├── numbers.md
│   │       ├── operators.md
│   │       ├── range.md
│   │       ├── strings.md
│   │       ├── switch.md
│   │       └── while.md
│   ├── docs.go
│   └── repl.go
├── sh/
│   └── install.sh
├── styles/
│   └── styles.go
├── third_party/
│   └── math/
│       ├── README.md
│       ├── hesabu.nr
│       └── test.nr
├── token/
│   └── token.go
└── upx

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/ISSUE_TEMPLATE/bug-report.yml
================================================
name: 🐛 Bug Report
description: Report a bug
title: (bug report summary)
labels: Bug
body:
  - type: textarea
    id: description
    attributes:
      label: Describe the bug
      description: What is the problem? A clear and concise description of the bug.
    validations:
      required: true

  - type: textarea
    id: expected
    attributes:
      label: Expected Behavior
      description: What did you expect to happen?
    validations:
      required: true

  - type: textarea
    id: current
    attributes:
      label: Current Behavior
      description: |
        What actually happened?

        Please include full errors, uncaught exceptions, stack traces, and relevant logs.
        If service/functions responses are relevant, please include wire logs.
    validations:
      required: true

  - type: textarea
    id: reproduction
    attributes:
      label: Reproduction Steps
      description: |
        Provide a self-contained, concise snippet of code that can be used to reproduce the issue.
        For more complex issues provide a repo with the smallest sample that reproduces the bug.

        Avoid including business logic or unrelated code, it makes diagnosis more difficult.
        The code sample should be an SSCCE. See http://sscce.org/ for details.
        In short, please provide a code sample that we can copy/paste, run and reproduce.
    validations:
      required: true

  - type: textarea
    id: solution
    attributes:
      label: Possible Solution
      description: Suggest a fix/reason for the bug
    validations:
      required: false

  - type: textarea
    id: context
    attributes:
      label: Additional Information/Context
      description: |
        Anything else that might be relevant for troubleshooting this bug.
        Providing context helps us come up with a solution that is most useful in the real world.
    validations:
      required: false

  - type: input
    id: version
    attributes:
      label: Nuru version
      description: |
        Please make sure to use the latest version of Nuru before reporting any issues as it may have already been fixed.
    validations:
      required: true

  - type: textarea
    id: environment
    attributes:
      label: Environment details (OS name and version, etc.)
      description: Your operating system (Windows, Linux, Android or MacOS)
    validations:
      required: true



================================================
FILE: .github/ISSUE_TEMPLATE/feature-request.yml
================================================
name: 🚀 Feature Request
description: Suggest an idea for this project
title: (feature request summary)
labels: Feature Request
body:
  - type: textarea
    id: description
    attributes:
      label: Describe the feature
      description: A clear and concise description of the feature you are proposing.
    validations:
      required: true

  - type: textarea
    id: use-case
    attributes:
      label: Use Case
      description: |
        Why do you need this feature? For example: "I'm always frustrated when..."
    validations:
      required: true

  - type: textarea
    id: solution
    attributes:
      label: Proposed Solution
      description: Suggest how to implement the addition or change. Please include prototype/workaround/sketch/reference implementation.
    validations:
      required: false

  - type: textarea
    id: other
    attributes:
      label: Other Information
      description: Any alternative solutions or features you considered, a more detailed explanation, stack traces, related issues, links for context, etc.
    validations:
      required: false

  - type: checkboxes
    id: ack
    attributes:
      label: Acknowledgements
      options:
        - label: I may be able to implement this feature request
          required: false

        - label: This feature might incur a breaking change
          required: false

  - type: input
    id: version
    attributes:
      label: Version used
      description: Please provide the version of the repository or tool you are using.
    validations:
      required: true

  - type: textarea
    id: environment
    attributes:
      label: Environment details (OS name and version, etc.)
      description: Your operating system (Linux, Windows, Android or Mac)
    validations:
      required: true



================================================
FILE: .github/PULL_REQUEST_TEMPLATE
================================================


<!--

Please title your PR as follows: `module: description` (e.g. `time: fix date format`).
Always start with the thing you are fixing, then describe the fix.
Don't use past tense (e.g. "fixed foo bar").

Explain what your PR does and why.

If you are adding a new function, please document it and add tests:

```
// foo does foo and bar
foo = unda() {
    // does foo and bar 
}
```

If you are fixing a bug, please add a detailed explanation about it.

Before submitting a PR, please run `make test` .

I try to process PRs as soon as possible. They should be handled within 24 hours.

Applying labels to PRs is not needed.

Thanks a lot for your contribution!

-->



================================================
FILE: .github/workflows/build.yml
================================================
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 }}


================================================
FILE: .github/workflows/tests.yml
================================================
name: Go

on:
  push:
    branches: [ main, dev ]

jobs:

  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Set up Go
      uses: actions/setup-go@v3
      with:
        go-version: 1.21

    - name: Test
      run: go mod tidy && make test



================================================
FILE: .gitignore
================================================
.DS_Store
*.[56789ao]
*.a[56789o]
*.so
*.pyc
._*
.nfs.*
[56789a].out
*~
*.orig
*.rej
*.exe
.*.swp
core
*.cgo*.go
*.cgo*.c
_cgo_*
_obj
_test
_testmain.go
/VERSION.cache
/bin/
/build.out
/doc/articles/wiki/*.bin
/goinstall.log
/last-change
/misc/cgo/life/run.out
/misc/cgo/stdio/run.out
/misc/cgo/testso/main
/pkg/
/src/*.*/
/src/cmd/cgo/zdefaultcc.go
/src/cmd/dist/dist
/src/cmd/go/internal/cfg/zdefaultcc.go
/src/cmd/go/internal/cfg/zosarch.go
/src/cmd/internal/objabi/zbootstrap.go
/src/go/build/zcgo.go
/src/go/doc/headscan
/src/runtime/internal/sys/zversion.go
/src/unicode/maketables
/test.out
/test/garbage/*.out
/test/pass.out
/test/run.out
/test/times.out

#Personal

testbinaries/
tests_random/
nuru
Notes.md
tutorials/en/*
config.json
*local*

# For Nuru executables
/nuru
/Nuru

dist/
*.wasm


================================================
FILE: .goreleaser.yaml
================================================
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 }}"


================================================
FILE: ABOUT.md
================================================
# NURU PROGRAMMING LANGUAGE

This page intends to show the origins of Nuru, its purpose, what it can be used for, what it should not be used for and the potential future of the programming language.

## Background

This language is the direct child of a programming language called "Monkey Language" made by Thorston Ball. He wrote a book titled "Writing An Interpreter In Go" and the core of the language is based on his book.

With the knowledge I gained from his book, I saw an opportunity to write a Swahili Programming Language, which would not just be a translation of an already existing one, but an actual standalone interpreted language that can be built from the ground up, where everything can be customized from the syntax, its abilities, its standard library and more. 

Now one may wonder, why a new programming language when there are many other much better programming languages in existence. The answer is, it is a Swahili programming language. And this is significant for two reasons:
- Many are unable to learn programming due to the language barrier. Almost all programming languages in existence are in English and thus a non English speaker would have to first learn English before they can learn a programming language. This makes the effort twice as difficult and Nuru, a native Swahili programming language, intends to make the process of learning programming languages a bit easier.
- Secondly, even if no one does use this programming language, then at least we can say "We do have a fully functional Swahili programming language", and as a person who grew up in Tanzania, this does give me pride.

## Purpose

Nuru does not intend to replace any existing programming language. In fact, it does not intend to be used in production at all. Nuru intends to be an educational programming language, a programming language that will make it easy for anyone to get into the world of programming without knowing English. It intends to be simple enough to be taught to kids in primary and highschool and allow them to build interesting tools with it.

Nuru also hopes to be used by hobbyists and experienced programmers, where by they will find it easy to write scripts in Nuru that will help solve their various tasks or build interesting projects with it. As a matter of fact, someone already made a sudoku solver in Nuru.

While being simple it also intends to be fully functional. Other than having all the core features required by a programming language, Nuru also has an extensive standard library that will make performing common tasks much easier. Thus, it intends to bring the best of both worlds, simple to use with a lot of features.

## Philosophy

Nuru's philosophy is to keep things simple. Everything in Nuru should be consistent and intuitive, from its syntax to the keywords used. On the matter of keywords, Nuru intends to provide keywords that are simple and intuitive that can easily explain what the function or library is for. A more detailed guide on the Nuru's syntax and the proper way of writing Nuru will be provided in the near future.

Nuru is also community driven. We listen to our community and do our best to implement on the feedback we get from them.

## Where Not To Use Nuru

Nuru's performance is worse than python. It has been authored by someone with very limited knowledge in programming. Thus, it is advised to never use Nuruin production code where by any kind of mistakes are critical. Nuru is still very immature and should only be used for educational and hobby projects.

## Challenges

The main challenge we have in Nuru is in naming keywords. Since this is something new, there are lack of words that fully describe common programming words. However, we do intend to try our best to select the best keywords, and we often consult with our community when choosing a word.

## Future Of Nuru

It is still too early to know how Nuru will evolve, or the way in which the community will use this language. However, what is certain is the core developers will do their best to provide a language that will be enjoyable to learn and code in. We listen to our community and hopefully we will soon have a large number of developers contributing to the language.

We also hope to see games and GUI applications written in Nuru in the near future... God willing.

## Final Words

I am very grateful to the reception of this project, we now have over 150+ downloads and its barely been a month. We hope to fulfill all your expectations and provide something that you will all enjoy to use. We also ask you to bear with us when we make mistakes and correct and advise us on areas where we can do better. I am also grateful to Thorston for writing such an amazing book, and I would recommend anyone who'd want to learn how programming languages work to read his book.

And finally, I thank Allah for granting us the ability to learn and giving me the ability to make such a project.


================================================
FILE: LICENSE
================================================
                    GNU GENERAL PUBLIC LICENSE
                       Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.

                    GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) You must cause the modified files to carry prominent notices
    stating that you changed the files and the date of any change.

    b) You must cause any work that you distribute or publish, that in
    whole or in part contains or is derived from the Program or any
    part thereof, to be licensed as a whole at no charge to all third
    parties under the terms of this License.

    c) If the modified program normally reads commands interactively
    when run, you must cause it, when started running for such
    interactive use in the most ordinary way, to print or display an
    announcement including an appropriate copyright notice and a
    notice that there is no warranty (or else, saying that you provide
    a warranty) and that users may redistribute the program under
    these conditions, and telling the user how to view a copy of this
    License.  (Exception: if the Program itself is interactive but
    does not normally print such an announcement, your work based on
    the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

    a) Accompany it with the complete corresponding machine-readable
    source code, which must be distributed under the terms of Sections
    1 and 2 above on a medium customarily used for software interchange; or,

    b) Accompany it with a written offer, valid for at least three
    years, to give any third party, for a charge no more than your
    cost of physically performing source distribution, a complete
    machine-readable copy of the corresponding source code, to be
    distributed under the terms of Sections 1 and 2 above on a medium
    customarily used for software interchange; or,

    c) Accompany it with the information you received as to the offer
    to distribute corresponding source code.  (This alternative is
    allowed only for noncommercial distribution and only if you
    received the program in object code or executable form with such
    an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

                            NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

    Gnomovision version 69, Copyright (C) year name of author
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
  `Gnomovision' (which makes passes at compilers) written by James Hacker.

  <signature of Ty Coon>, 1 April 1989
  Ty Coon, President of Vice

This General Public License does not permit incorporating your program into
proprietary programs.  If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.


================================================
FILE: Makefile
================================================
VERSION=0.5.1

build_linux:
	@echo 'building linux binary...'
	env GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o nuru
	@echo 'shrinking binary...'
	./upx --brute nuru
	@echo 'zipping build....'
	tar -zcvf nuru_linux_amd64_v${VERSION}.tar.gz nuru
	@echo 'cleaning up...'
	rm nuru

build_windows:
	@echo 'building windows executable...'
	env GOOS=windows GOARCH=amd64 go build -ldflags="-s -w" -o nuru_windows_amd64_v${VERSION}.exe
	@echo 'shrinking build...'
	./upx --brute nuru_windows_amd64_v${VERSION}.exe

build_mac:
	@echo 'building mac binary...'
	env GOOS=darwin GOARCH=amd64 go build -ldflags="-s -w" -o nuru
	@echo 'shrinking binary...'
	./upx --brute nuru
	@echo 'zipping build...'
	tar -zcvf nuru_mac_amd64_v${VERSION}.tar.gz nuru
	@echo 'cleaning up...'
	rm nuru

build_android:
	@echo 'building android binary'
	env GOOS=android GOARCH=arm64 go build -ldflags="-s -w" -o nuru
	@echo 'zipping build...'
	tar -zcvf nuru_android_arm64_v${VERSION}.tar.gz nuru
	@echo 'cleaning up...'
	rm nuru

build_wasm:
	@echo 'building wasm binary'
	GOOS=js GOARCH=wasm go build -o nuru.wasm
	@echo 'zipping build...'
	tar -zcvf nuru_wasm_v${VERSION}.tar.gz nuru.wasm
	@echo 'cleaning up...'
	rm nuru.wasm


build_test:
	go build -ldflags="-s -w" -o nuru

dependencies:
	@echo 'checking dependencies...'
	go mod tidy

test:
	@echo -e '\nTesting Lexer...'
	@./gotest --format testname ./lexer/ 
	@echo -e '\nTesting Parser...'
	@./gotest --format testname ./parser/
	@echo -e '\nTesting AST...'
	@./gotest --format testname ./ast/
	@echo -e '\nTesting Object...'
	@./gotest --format testname ./object/
	@echo -e '\nTesting Evaluator...'
	@./gotest --format testname ./evaluator/

clean:
	go clean


================================================
FILE: README.md
================================================
<h1 align="center">NURU🔥PROGRAMMING🔥LANGUAGE</h1>
<p align="center">
    <a href="https://github.com/NuruProgramming/Nuru"><img alt="Nuru Programming Language" src="https://img.shields.io/badge/Nuru-Programming%20Language-yellow"></a>
    <a href="https://github.com/NuruProgramming/Nuru"><img alt="Nuru Programming Language" src="https://img.shields.io/badge/platform-Linux | Windows | Android-green.svg"></a>
    <a href="https://github.com/NuruProgramming/Nuru"><img alt="Nuru Programming Language" src="https://img.shields.io/github/last-commit/AvicennaJr/Nuru"></a>
<br>
    <a href="https://github.com/NuruProgramming/Nuru"><img alt="Nuru Programming Language" src="https://img.shields.io/github/downloads/avicennajr/nuru/total"></a>
    <a href="https://github.com/NuruProgramming/Nuru/releases"><img alt="Nuru Programming Language" src="https://img.shields.io/github/v/release/avicennajr/nuru?include_prereleases"></a>
    <a href="https://github.com/NuruProgramming/Nuru"><img alt="Nuru Programming Language" src="https://img.shields.io/github/actions/workflow/status/AvicennaJr/Nuru/tests.yml?style=plastic"></a>
<br>
    <a href="https://github.com/NuruProgramming/Nuru"><img alt="Nuru Programming Language" src="https://img.shields.io/github/stars/AvicennaJr/Nuru?style=social"></a>
</p>
A Swahili Programming Language of its kind built from the ground up.

## Installation

To get started download the executables from the release page or follow the instructions for your device below:

### Linux

- Download the binary:

```
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:

```
sudo tar -C /usr/local/bin -xzvf nuru_Linux_amd64.tar.gz
```

- Confirm installation with:

```
nuru -v
```

### MacOs ( Apple silicon Mac )

- Download the binary:

  - For apple silicon mac use:

    ```
    curl -O -L https://github.com/NuruProgramming/Nuru/releases/download/v0.5.18/nuru_Darwin_arm64.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:

  - 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)

To install Nuru on your Android device using Termux, follow these steps:

1. **Ensure Termux is installed**:

   - You can download and install [Termux](https://f-droid.org/en/packages/com.termux/).

2. **Create the target directory**:

   ```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 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

### Building From Source

- Make sure you have golang installed (atleast 1.19.0 and above)
- Run the following command:

```
go build -o nuru .
```

- Copy nuru binary to path destination ~/go/bin

```
cp nuru ~/go/bin
```

- Confirm installtion with:

```
nuru -v
```

## Syntax At A Glance

**NOTE**

> 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.

### Defining A Variable

You can define variables like this:

```
x = 2;
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

Nuru supports both single line and multiple line comments as shown below:

```
// Single line comment

/*
Multiple
Line
Comment
*/
```

### Arithmetic Operations

For now Nuru supports `+`, `-`, `/`, `*` and `%`. Nuru also provides precedence of operations using the BODMAS rule:

```
2 + 2 * 3 // output = 8

2 * (2 + 3) // output = 10
```

### Types

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                                   |

### Functions

This is how you define a function in Nuru:

```
jumlisha = unda(x, y) {
        rudisha x + y
    }

andika(jumlisha(3,4))
```

Nuru also supports recursion:

```
fibo = unda(x) {
	kama (x == 0) {
		rudisha 0;
	} au kama (x == 1) {
			rudisha 1;
	} sivyo {
			rudisha fibo(x - 1) + fibo(x - 2);
	}
}
```

### If Statements

Nuru supports if, elif and else statements with keywords `kama`, `au kama` and `sivyo` respectively:

```
kama (2<1) {
    andika("Mbili ni ndogo kuliko moja")
} au kama (3 < 1) {
    andika ("Tatu ni ndogo kuliko moja")
} sivyo {
    andika("Moja ni ndogo")
}
```

### While Loops

Nuru's while loop syntax is as follows:

```
i = 10

wakati (i > 0) {
	andika(i)
	i--
}
```

### Arrays

This is how you initiliaze and perform other array operations in Nuru:

```
arr = []

// To add elements

sukuma(arr, 2)
andika(arr) // output = [2]
// Add two Arrays

arr2 = [1,2,3,4]

arr3 = arr1 + arr2

andika(arr3) // output = [2,1,2,3,4]

// reassign value

arr3[0] = 0

andika[arr3] // output = [0,1,2,3,4]

// get specific item

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
andika(mtu["jina"]) // output = Mojo

andika(mtu["kabila"]); // output = Mnyakusa

// You can reassign values

mtu["jina"] = "Avicenna"

andika(mtu["jina"]) // output = Avicenna

// You can also add new values like this:

mtu["anapoishi"] = "Dar Es Salaam"

andika(mtu) // output = {"jina": "Avicenna", "kabila": "Mnyakusa", "anapoishi": "Dar Es Salaam"}

// You can also add two Dictionaries

kazi = {"kazi": "jambazi"}

mtu = mtu + kazi

andika(mtu) // output = {"jina": "Avicenna", "kabila": "Mnyakusa", "anapoishi": "Dar Es Salaam", "kazi": "jambazi"}
```

### For Loops

These can iterate over strings, arrays and dictionaries:

```
kwa i ktk "habari" {
    andika(i)
}
/* //output
h
a
b
a
r
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

andika("Habari yako " + jina)
```

## How To Run

### Using The Intepreter:

You can enter the intepreter by simply running the `nuru` command:

```
nuru
>>> andika("karibu")
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:

```
nuru myFile.nr
```

## Issues

Kindly open an [Issue](https://github.com/NuruProgramming/Nuru/issues) to make suggestions and anything else.

## Contributions

### Documentation

There are documentations for two languages, English and Kiswahili, which are both under the `docs` folder. All files are written in markdown. Feel free to contribute by making a pull request.

### Code

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 test`

## Community

Nuru has a passionate community, join us on [Telegram](https://t.me/NuruProgrammingChat)

## License

[MIT](http://opensource.org/licenses/MIT)

## Authors

Nuru Programming Language has been authored and being actively maintained by [Avicenna](https://github.com/AvicennaJr)


================================================
FILE: ast/ast.go
================================================
package ast

import (
	"bytes"
	"strings"

	"github.com/NuruProgramming/Nuru/token"
)

type Node interface {
	TokenLiteral() string
	String() string
}

type Statement interface {
	Node
	statementNode()
}

type Expression interface {
	Node
	expressionNode()
}

type Program struct {
	Statements []Statement
}

func (p *Program) TokenLiteral() string {
	if len(p.Statements) > 0 {
		return p.Statements[0].TokenLiteral()
	} else {
		return ""
	}
}

func (p *Program) String() string {
	var out bytes.Buffer

	for _, s := range p.Statements {
		out.WriteString(s.String())
	}

	return out.String()
}

type LetStatement struct {
	Token token.Token
	Name  *Identifier
	Value Expression
}

func (ls *LetStatement) statementNode()       {}
func (ls *LetStatement) TokenLiteral() string { return ls.Token.Literal }
func (ls *LetStatement) String() string {
	var out bytes.Buffer

	out.WriteString(ls.TokenLiteral() + " ")
	out.WriteString(ls.Name.String())
	out.WriteString(" = ")

	if ls.Value != nil {
		out.WriteString(ls.Value.String())
	}

	out.WriteString(";")
	return out.String()
}

type Identifier struct {
	Token token.Token
	Value string
}

func (i *Identifier) expressionNode()      {}
func (i *Identifier) TokenLiteral() string { return i.Token.Literal }
func (i *Identifier) String() string       { return i.Value }

type ReturnStatement struct {
	Token       token.Token
	ReturnValue Expression
}

func (rs *ReturnStatement) statementNode()       {}
func (rs *ReturnStatement) TokenLiteral() string { return rs.Token.Literal }
func (rs *ReturnStatement) String() string {
	var out bytes.Buffer

	out.WriteString(rs.TokenLiteral() + " ")

	if rs.ReturnValue != nil {
		out.WriteString(rs.ReturnValue.String())
	}
	out.WriteString(";")
	return out.String()
}

type ExpressionStatement struct {
	Token      token.Token
	Expression Expression
}

func (es *ExpressionStatement) statementNode()       {}
func (es *ExpressionStatement) TokenLiteral() string { return es.Token.Literal }
func (es *ExpressionStatement) String() string {
	if es.Expression != nil {
		return es.Expression.String()
	}

	return ""
}

type IntegerLiteral struct {
	Token token.Token
	Value int64
}

func (il *IntegerLiteral) expressionNode()      {}
func (il *IntegerLiteral) TokenLiteral() string { return il.Token.Literal }
func (il *IntegerLiteral) String() string       { return il.Token.Literal }

type PrefixExpression struct {
	Token    token.Token
	Operator string
	Right    Expression
}

func (pe *PrefixExpression) expressionNode()      {}
func (pe *PrefixExpression) TokenLiteral() string { return pe.Token.Literal }
func (pe *PrefixExpression) String() string {
	var out bytes.Buffer

	out.WriteString("(")
	out.WriteString(pe.Operator)
	out.WriteString(pe.Right.String())
	out.WriteString(")")

	return out.String()
}

type InfixExpression struct {
	Token    token.Token
	Left     Expression
	Operator string
	Right    Expression
}

func (oe *InfixExpression) expressionNode()      {}
func (oe *InfixExpression) TokenLiteral() string { return oe.Token.Literal }
func (oe *InfixExpression) String() string {
	var out bytes.Buffer

	out.WriteString("(")
	out.WriteString(oe.Left.String())
	out.WriteString(" " + oe.Operator + " ")
	out.WriteString(oe.Right.String())
	out.WriteString(")")

	return out.String()
}

type Boolean struct {
	Token token.Token
	Value bool
}

func (b *Boolean) expressionNode()      {}
func (b *Boolean) TokenLiteral() string { return b.Token.Literal }
func (b *Boolean) String() string       { return b.Token.Literal }

type IfExpression struct {
	Token       token.Token
	Condition   Expression
	Consequence *BlockStatement
	Alternative *BlockStatement
}

func (ie *IfExpression) expressionNode()      {}
func (ie *IfExpression) TokenLiteral() string { return ie.Token.Literal }
func (ie *IfExpression) String() string {
	var out bytes.Buffer
	out.WriteString("kama")
	out.WriteString(ie.Condition.String())
	out.WriteString(" ")
	out.WriteString(ie.Consequence.String())

	if ie.Alternative != nil {
		out.WriteString("sivyo")
		out.WriteString(ie.Alternative.String())
	}

	return out.String()
}

type BlockStatement struct {
	Token      token.Token
	Statements []Statement
}

func (bs *BlockStatement) statementNode()       {}
func (bs *BlockStatement) TokenLiteral() string { return bs.Token.Literal }
func (bs *BlockStatement) String() string {
	var out bytes.Buffer

	for _, s := range bs.Statements {
		out.WriteString(s.String())
	}

	return out.String()
}

type FunctionLiteral struct {
	Token      token.Token
	Name       string
	Parameters []*Identifier
	Defaults   map[string]Expression
	Body       *BlockStatement
}

func (fl *FunctionLiteral) expressionNode()      {}
func (fl *FunctionLiteral) TokenLiteral() string { return fl.Token.Literal }
func (fl *FunctionLiteral) String() string {
	var out bytes.Buffer

	params := []string{}

	for _, p := range fl.Parameters {
		params = append(params, p.String())
	}

	out.WriteString(fl.TokenLiteral())
	out.WriteString("(")
	out.WriteString(strings.Join(params, ", "))
	out.WriteString(") ")
	out.WriteString(fl.Body.String())

	return out.String()
}

type CallExpression struct {
	Token     token.Token
	Function  Expression // can be Identifier or FunctionLiteral
	Arguments []Expression
}

func (ce *CallExpression) expressionNode()      {}
func (ce *CallExpression) TokenLiteral() string { return ce.Token.Literal }
func (ce *CallExpression) String() string {
	var out bytes.Buffer

	args := []string{}
	for _, a := range ce.Arguments {
		args = append(args, a.String())
	}

	out.WriteString(ce.Function.String())
	out.WriteString("(")
	out.WriteString(strings.Join(args, ", "))
	out.WriteString(")")

	return out.String()
}

type StringLiteral struct {
	Token token.Token
	Value string
}

func (sl *StringLiteral) expressionNode()      {}
func (sl *StringLiteral) TokenLiteral() string { return sl.Token.Literal }
func (sl *StringLiteral) String() string       { return sl.Token.Literal }

type ArrayLiteral struct {
	Token    token.Token
	Elements []Expression
}

func (al *ArrayLiteral) expressionNode()      {}
func (al *ArrayLiteral) TokenLiteral() string { return al.Token.Literal }
func (al *ArrayLiteral) String() string {
	var out bytes.Buffer

	elements := []string{}
	for _, el := range al.Elements {
		elements = append(elements, el.String())
	}

	out.WriteString("[")
	out.WriteString(strings.Join(elements, ", "))
	out.WriteString("]")

	return out.String()
}

type IndexExpression struct {
	Token token.Token
	Left  Expression
	Index Expression
}

func (ie *IndexExpression) expressionNode()      {}
func (ie *IndexExpression) TokenLiteral() string { return ie.Token.Literal }
func (ie *IndexExpression) String() string {
	var out bytes.Buffer

	out.WriteString("(")
	out.WriteString(ie.Left.String())
	out.WriteString("[")
	out.WriteString(ie.Index.String())
	out.WriteString("])")

	return out.String()
}

type DictLiteral struct {
	Token token.Token
	Pairs map[Expression]Expression
}

func (dl *DictLiteral) expressionNode()      {}
func (dl *DictLiteral) TokenLiteral() string { return dl.Token.Literal }
func (dl *DictLiteral) String() string {
	var out bytes.Buffer
	pairs := []string{}
	for key, value := range dl.Pairs {
		pairs = append(pairs, key.String()+":"+value.String())
	}

	out.WriteString("(")
	out.WriteString(strings.Join(pairs, ", "))
	out.WriteString("}")

	return out.String()
}

type Assign struct {
	Token token.Token
	Name  *Identifier
	Value Expression
}

func (ae *Assign) expressionNode()      {}
func (ae *Assign) TokenLiteral() string { return ae.Token.Literal }
func (ae *Assign) String() string {
	var out bytes.Buffer

	out.WriteString(ae.Name.String())
	out.WriteString(ae.TokenLiteral())
	out.WriteString(ae.Value.String())

	return out.String()
}

type AssignEqual struct {
	Token token.Token
	Left  *Identifier
	Value Expression
}

func (ae *AssignEqual) expressionNode()      {}
func (ae *AssignEqual) TokenLiteral() string { return ae.Token.Literal }
func (ae *AssignEqual) String() string {
	var out bytes.Buffer

	out.WriteString(ae.Left.String())
	out.WriteString(ae.TokenLiteral())
	out.WriteString(ae.Value.String())

	return out.String()
}

type AssignmentExpression struct {
	Token token.Token
	Left  Expression
	Value Expression
}

func (ae *AssignmentExpression) expressionNode()      {}
func (ae *AssignmentExpression) TokenLiteral() string { return ae.Token.Literal }
func (ae *AssignmentExpression) String() string {
	var out bytes.Buffer

	out.WriteString(ae.Left.String())
	out.WriteString(ae.TokenLiteral())
	out.WriteString(ae.Value.String())

	return out.String()
}

type WhileExpression struct {
	Token       token.Token
	Condition   Expression
	Consequence *BlockStatement
}

func (we *WhileExpression) expressionNode()      {}
func (we *WhileExpression) TokenLiteral() string { return we.Token.Literal }
func (we *WhileExpression) String() string {
	var out bytes.Buffer

	out.WriteString("wakati")
	out.WriteString(we.Condition.String())
	out.WriteString(" ")
	out.WriteString(we.Consequence.String())

	return out.String()
}

type Null struct {
	Token token.Token
}

func (n *Null) expressionNode()      {}
func (n *Null) TokenLiteral() string { return n.Token.Literal }
func (n *Null) String() string       { return n.Token.Literal }

type Break struct {
	Statement
	Token token.Token // the 'break' token
}

func (b *Break) expressionNode()      {}
func (b *Break) TokenLiteral() string { return b.Token.Literal }
func (b *Break) String() string       { return b.Token.Literal }

type Continue struct {
	Statement
	Token token.Token // the 'continue' token
}

func (c *Continue) expressionNode()      {}
func (c *Continue) TokenLiteral() string { return c.Token.Literal }
func (c *Continue) String() string       { return c.Token.Literal }

type PostfixExpression struct {
	Token    token.Token
	Operator string
}

func (pe *PostfixExpression) expressionNode()      {}
func (pe *PostfixExpression) TokenLiteral() string { return pe.Token.Literal }
func (pe *PostfixExpression) String() string {
	var out bytes.Buffer
	out.WriteString("(")
	out.WriteString(pe.Token.Literal)
	out.WriteString(pe.Operator)
	out.WriteString(")")
	return out.String()
}

type FloatLiteral struct {
	Token token.Token
	Value float64
}

func (fl *FloatLiteral) expressionNode()      {}
func (fl *FloatLiteral) TokenLiteral() string { return fl.Token.Literal }
func (fl *FloatLiteral) String() string       { return fl.Token.Literal }

type For struct {
	Token        token.Token
	Identifier   string      // "i"
	StarterName  *Identifier // i = 0
	StarterValue Expression
	Closer       Expression // i++
	Condition    Expression // i < 1
	Block        *BlockStatement
}

type ForIn struct {
	Token    token.Token
	Key      string
	Value    string
	Iterable Expression
	Block    *BlockStatement
}

func (fi *ForIn) expressionNode()      {}
func (fi *ForIn) TokenLiteral() string { return fi.Token.Literal }
func (fi *ForIn) String() string {
	var out bytes.Buffer

	out.WriteString("kwa ")
	if fi.Key != "" {
		out.WriteString(fi.Key + ", ")
	}
	out.WriteString(fi.Value + " ")
	out.WriteString("ktk ")
	out.WriteString(fi.Iterable.String() + " {\n")
	out.WriteString("\t" + fi.Block.String())
	out.WriteString("\n}")

	return out.String()
}

type CaseExpression struct {
	Token   token.Token
	Default bool
	Expr    []Expression
	Block   *BlockStatement
}

func (ce *CaseExpression) expressionNode()      {}
func (ce *CaseExpression) TokenLiteral() string { return ce.Token.Literal }
func (ce *CaseExpression) String() string {
	var out bytes.Buffer

	if ce.Default {
		out.WriteString("kawaida ")
	} else {
		out.WriteString("ikiwa ")

		tmp := []string{}
		for _, exp := range ce.Expr {
			tmp = append(tmp, exp.String())
		}
		out.WriteString(strings.Join(tmp, ","))
	}
	out.WriteString(ce.Block.String())
	return out.String()
}

type SwitchExpression struct {
	Token   token.Token
	Value   Expression
	Choices []*CaseExpression
}

func (se *SwitchExpression) expressionNode()      {}
func (se *SwitchExpression) TokenLiteral() string { return se.Token.Literal }
func (se *SwitchExpression) String() string {
	var out bytes.Buffer
	out.WriteString("\nbadili (")
	out.WriteString(se.Value.String())
	out.WriteString(")\n{\n")

	for _, tmp := range se.Choices {
		if tmp != nil {
			out.WriteString(tmp.String())
		}
	}
	out.WriteString("}\n")

	return out.String()
}

type MethodExpression struct {
	Token     token.Token
	Object    Expression
	Method    Expression
	Arguments []Expression
	Defaults  map[string]Expression
}

func (me *MethodExpression) expressionNode()      {}
func (me *MethodExpression) TokenLiteral() string { return me.Token.Literal }
func (me *MethodExpression) String() string {
	var out bytes.Buffer
	out.WriteString(me.Object.String())
	out.WriteString(".")
	out.WriteString(me.Method.String())

	return out.String()
}

type Import struct {
	Token       token.Token
	Identifiers map[string]*Identifier
}

func (i *Import) expressionNode()      {}
func (i *Import) TokenLiteral() string { return i.Token.Literal }
func (i *Import) String() string {
	var out bytes.Buffer
	out.WriteString("tumia ")
	for k := range i.Identifiers {
		out.WriteString(k + " ")
	}
	return out.String()
}

type PackageBlock struct {
	Token      token.Token
	Statements []Statement
}

func (pb *PackageBlock) statementNode()       {}
func (pb *PackageBlock) TokenLiteral() string { return pb.Token.Literal }
func (pb *PackageBlock) String() string {
	var out bytes.Buffer

	for _, s := range pb.Statements {
		out.WriteString(s.String())
	}

	return out.String()
}

type Package struct {
	Token token.Token
	Name  *Identifier
	Block *BlockStatement
}

func (p *Package) expressionNode()      {}
func (p *Package) TokenLiteral() string { return p.Token.Literal }
func (p *Package) String() string {
	var out bytes.Buffer

	out.WriteString("pakeji " + p.Name.Value + "\n")
	out.WriteString("::\n")
	for _, s := range p.Block.Statements {
		out.WriteString(s.String())
	}
	out.WriteString("\n::")

	return out.String()
}

type At struct {
	Token token.Token
}

func (a *At) expressionNode()      {}
func (a *At) TokenLiteral() string { return a.Token.Literal }
func (a *At) String() string       { return "@" }

type PropertyAssignment struct {
	Token token.Token // the '=' token
	Name  *PropertyExpression
	Value Expression
}

func (pa *PropertyAssignment) expressionNode()      {}
func (pa *PropertyAssignment) TokenLiteral() string { return pa.Token.Literal }
func (pa *PropertyAssignment) String() string       { return "Ngl I'm tired" }

type PropertyExpression struct {
	Expression
	Token    token.Token // The . token
	Object   Expression
	Property Expression
}

func (pe *PropertyExpression) expressionNode()      {}
func (pe *PropertyExpression) TokenLiteral() string { return pe.Token.Literal }
func (pe *PropertyExpression) String() string       { return "Ngl I'm tired part two" }


================================================
FILE: ast/ast_test.go
================================================
package ast

import (
	"testing"

	"github.com/NuruProgramming/Nuru/token"
)

func TestString(t *testing.T) {
	program := &Program{
		Statements: []Statement{
			&LetStatement{
				Token: token.Token{Type: token.LET, Literal: "fanya"},
				Name: &Identifier{
					Token: token.Token{Type: token.IDENT, Literal: "myVar"},
					Value: "myVar",
				},
				Value: &Identifier{
					Token: token.Token{Type: token.IDENT, Literal: "anotherVar"},
					Value: "anotherVar",
				},
			},
		},
	}

	if program.String() != "fanya myVar = anotherVar;" {
		t.Errorf("program.String() wrong. got=%q", program.String())
	}
}


================================================
FILE: evaluator/assign.go
================================================
package evaluator

import (
	"github.com/NuruProgramming/Nuru/ast"
	"github.com/NuruProgramming/Nuru/object"
)

func evalAssign(node *ast.Assign, env *object.Environment) object.Object {
	val := Eval(node.Value, env)
	if isError(val) {
		return val
	}

	obj := env.Set(node.Name.Value, val)
	return obj
}


================================================
FILE: evaluator/assignEqual.go
================================================
package evaluator

import (
	"strings"

	"github.com/NuruProgramming/Nuru/ast"
	"github.com/NuruProgramming/Nuru/object"
)

func evalAssignEqual(node *ast.AssignEqual, env *object.Environment) object.Object {
	left := Eval(node.Left, env)
	if isError(left) {
		return left
	}

	value := Eval(node.Value, env)
	if isError(value) {
		return value
	}

	switch node.Token.Literal {
	case "+=":
		switch arg := left.(type) {
		case *object.Integer:
			switch val := value.(type) {
			case *object.Integer:
				v := arg.Value + val.Value
				return env.Set(node.Left.Token.Literal, &object.Integer{Value: v})
			case *object.Float:
				v := float64(arg.Value) + val.Value
				return env.Set(node.Left.Token.Literal, &object.Float{Value: v})
			default:
				return newError("Mstari %d: Huwezi kutumia '+=' kujumlisha %v na %v", node.Token.Line, arg.Type(), val.Type())
			}
		case *object.Float:
			switch val := value.(type) {
			case *object.Integer:
				v := arg.Value + float64(val.Value)
				return env.Set(node.Left.Token.Literal, &object.Float{Value: v})
			case *object.Float:
				v := arg.Value + val.Value
				return env.Set(node.Left.Token.Literal, &object.Float{Value: v})
			default:
				return newError("Mstari %d: Huwezi kutumia '+=' kujumlisha %v na %v", node.Token.Line, arg.Type(), val.Type())
			}
		case *object.String:
			switch val := value.(type) {
			case *object.String:
				v := arg.Value + val.Value
				return env.Set(node.Left.Token.Literal, &object.String{Value: v})
			default:
				return newError("Mstari %d: Huwezi kutumia '+=' kwa %v na %v", node.Token.Line, arg.Type(), val.Type())
			}
		default:
			return newError("Mstari %d: Huwezi kutumia '+=' na %v", node.Token.Line, arg.Type())
		}
	case "-=":
		switch arg := left.(type) {
		case *object.Integer:
			switch val := value.(type) {
			case *object.Integer:
				v := arg.Value - val.Value
				return env.Set(node.Left.Token.Literal, &object.Integer{Value: v})
			case *object.Float:
				v := float64(arg.Value) - val.Value
				return env.Set(node.Left.Token.Literal, &object.Float{Value: v})
			default:
				return newError("Mstari %d: Huwezi kutumia '-=' kujumlisha %v na %v", node.Token.Line, arg.Type(), val.Type())
			}
		case *object.Float:
			switch val := value.(type) {
			case *object.Integer:
				v := arg.Value - float64(val.Value)
				return env.Set(node.Left.Token.Literal, &object.Float{Value: v})
			case *object.Float:
				v := arg.Value - val.Value
				return env.Set(node.Left.Token.Literal, &object.Float{Value: v})
			default:
				return newError("Mstari %d: Huwezi kutumia '-=' kujumlisha %v na %v", node.Token.Line, arg.Type(), val.Type())
			}
		default:
			return newError("Mstari %d: Huwezi kutumia '-=' na %v", node.Token.Line, arg.Type())
		}
	case "*=":
		switch arg := left.(type) {
		case *object.Integer:
			switch val := value.(type) {
			case *object.Integer:
				v := arg.Value * val.Value
				return env.Set(node.Left.Token.Literal, &object.Integer{Value: v})
			case *object.Float:
				v := float64(arg.Value) * val.Value
				return env.Set(node.Left.Token.Literal, &object.Float{Value: v})
			case *object.String:
				v := strings.Repeat(val.Value, int(arg.Value))
				return env.Set(node.Left.Token.Literal, &object.String{Value: v})
			default:
				return newError("Mstari %d: Huwezi kutumia '*=' kujumlisha %v na %v", node.Token.Line, arg.Type(), val.Type())
			}
		case *object.Float:
			switch val := value.(type) {
			case *object.Integer:
				v := arg.Value * float64(val.Value)
				return env.Set(node.Left.Token.Literal, &object.Float{Value: v})
			case *object.Float:
				v := arg.Value * val.Value
				return env.Set(node.Left.Token.Literal, &object.Float{Value: v})
			default:
				return newError("Mstari %d: Huwezi kutumia '*=' kujumlisha %v na %v", node.Token.Line, arg.Type(), val.Type())
			}
		case *object.String:
			switch val := value.(type) {
			case *object.Integer:
				v := strings.Repeat(arg.Value, int(val.Value))
				return env.Set(node.Left.Token.Literal, &object.String{Value: v})
			default:
				return newError("Mstari %d: Huwezi kutumia '+=' kwa %v na %v", node.Token.Line, arg.Type(), val.Type())
			}
		default:
			return newError("Mstari %d: Huwezi kutumia '*=' na %v", node.Token.Line, arg.Type())
		}
	case "/=":
		switch arg := left.(type) {
		case *object.Integer:
			switch val := value.(type) {
			case *object.Integer:
				v := arg.Value / val.Value
				return env.Set(node.Left.Token.Literal, &object.Integer{Value: v})
			case *object.Float:
				v := float64(arg.Value) / val.Value
				return env.Set(node.Left.Token.Literal, &object.Float{Value: v})
			default:
				return newError("Mstari %d: Huwezi kutumia '/=' kujumlisha %v na %v", node.Token.Line, arg.Type(), val.Type())
			}
		case *object.Float:
			switch val := value.(type) {
			case *object.Integer:
				v := arg.Value / float64(val.Value)
				return env.Set(node.Left.Token.Literal, &object.Float{Value: v})
			case *object.Float:
				v := arg.Value / val.Value
				return env.Set(node.Left.Token.Literal, &object.Float{Value: v})
			default:
				return newError("Mstari %d: Huwezi kutumia '/=' kujumlisha %v na %v", node.Token.Line, arg.Type(), val.Type())
			}
		default:
			return newError("Mstari %d: Huwezi kutumia '/=' na %v", node.Token.Line, arg.Type())
		}
	default:
		return newError("Mstari %d: Operesheni Haifahamiki  %s", node.Token.Line, node.Token.Literal)
	}
}


================================================
FILE: evaluator/at.go
================================================
package evaluator

import (
	"github.com/NuruProgramming/Nuru/ast"
	"github.com/NuruProgramming/Nuru/object"
)

func evalAt(node *ast.At, env *object.Environment) object.Object {
	if at, ok := env.Get("@"); ok {
		return at
	}
	return newError("Iko nje ya scope")
}


================================================
FILE: evaluator/bang.go
================================================
package evaluator

import "github.com/NuruProgramming/Nuru/object"

func evalBangOperatorExpression(right object.Object) object.Object {
	switch right {
	case TRUE:
		return FALSE
	case FALSE:
		return TRUE
	case NULL:
		return TRUE
	default:
		return FALSE
	}
}


================================================
FILE: evaluator/block.go
================================================
package evaluator

import (
	"github.com/NuruProgramming/Nuru/ast"
	"github.com/NuruProgramming/Nuru/object"
)

func evalBlockStatement(block *ast.BlockStatement, env *object.Environment) object.Object {
	var result object.Object

	for _, statement := range block.Statements {
		result = Eval(statement, env)

		if result != nil {
			rt := result.Type()
			if rt == object.RETURN_VALUE_OBJ || rt == object.ERROR_OBJ || rt == object.CONTINUE_OBJ || rt == object.BREAK_OBJ {
				return result
			}
		}
	}

	return result
}


================================================
FILE: evaluator/builtins.go
================================================
//go:build !js || !wasm 

package evaluator

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/NuruProgramming/Nuru/object"
)

var builtins = map[string]*object.Builtin{
	"jaza": {
		Fn: func(args ...object.Object) object.Object {

			if len(args) > 1 {
				return newError("Samahani, kiendesha hiki kinapokea hoja 0 au 1, wewe umeweka %d", len(args))
			}

			if len(args) > 0 && args[0].Type() != object.STRING_OBJ {
				return newError(fmt.Sprintf(`Tafadhali tumia alama ya nukuu: "%s"`, args[0].Inspect()))
			}
			if len(args) == 1 {
				prompt := args[0].(*object.String).Value
				fmt.Fprint(os.Stdout, prompt)
			}

			buffer := bufio.NewReader(os.Stdin)

			line, _, err := buffer.ReadLine()
			if err != nil && err != io.EOF {
				return newError("Nimeshindwa kusoma uliyo yajaza")
			}

			return &object.String{Value: string(line)}
		},
	},
	"andika": {
		Fn: func(args ...object.Object) object.Object {
			if len(args) == 0 {
				fmt.Println("")
			} else {
				var arr []string
				for _, arg := range args {
					if arg == nil {
						return newError("Hauwezi kufanya operesheni hii")
					}
					arr = append(arr, arg.Inspect())
				}
				str := strings.Join(arr, " ")
				fmt.Println(str)
			}
			return nil
		},
	},
	"_andika": {
		Fn: func(args ...object.Object) object.Object {
			if len(args) == 0 {
				return &object.String{Value: "\n"}
			} else {
				var arr []string
				for _, arg := range args {
					if arg == nil {
						return newError("Hauwezi kufanya operesheni hii")
					}
					arr = append(arr, arg.Inspect())
				}
				str := strings.Join(arr, " ")
				return &object.String{Value: str}
			}
		},
	},

}

func init(){
	for name, builtin := range commonBuiltins{
		builtins[name]=builtin
	}
}

================================================
FILE: evaluator/builtins_common.go
================================================
package evaluator

import (
	"fmt"
	"os"
	"strings"

	"github.com/NuruProgramming/Nuru/object"
)

var commonBuiltins = map[string]*object.Builtin{
	"_andika": {
		Fn: func(args ...object.Object) object.Object {
			if len(args) == 0 {
				return &object.String{Value: "\n"}
			} else {
				var arr []string
				for _, arg := range args {
					if arg == nil {
						return newError("Hauwezi kufanya operesheni hii")
					}
					arr = append(arr, arg.Inspect())
				}
				str := strings.Join(arr, " ")
				return &object.String{Value: str}
			}
		},
	},
	"aina": {
		Fn: func(args ...object.Object) object.Object {
			if len(args) != 1 {
				return newError("Samahani, tunahitaji hoja 1, wewe umeweka %d", len(args))
			}

			return &object.String{Value: string(args[0].Type())}
		},
	},
	"fungua": {
		Fn: func(args ...object.Object) object.Object {

			if len(args) != 1 {
				return newError("Samahani, tunahitaji hoja 1, wewe umeweka %d", len(args))
			}
			filename := args[0].(*object.String).Value

			file, err := os.ReadFile(filename)
			if err != nil {
				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 {
	// 		if len(args) != 1 {
	// 			return newError("Hoja hazilingani, tunahitaji=1, tumepewa=%d", len(args))
	// 		}

	// 		switch arg := args[0].(type) {
	// 		case *object.Array:

	// 			var sums float64
	// 			for _, num := range arg.Elements {

	// 				if num.Type() != object.INTEGER_OBJ && num.Type() != object.FLOAT_OBJ {
	// 					return newError("Samahani namba tu zinahitajika")
	// 				} else {
	// 					if num.Type() == object.INTEGER_OBJ {
	// 						no, _ := strconv.Atoi(num.Inspect())
	// 						floatnum := float64(no)
	// 						sums += floatnum
	// 					} else if num.Type() == object.FLOAT_OBJ {
	// 						no, _ := strconv.ParseFloat(num.Inspect(), 64)
	// 						sums += no
	// 					}

	// 				}
	// 			}

	// 			if math.Mod(sums, 1) == 0 {
	// 				return &object.Integer{Value: int64(sums)}
	// 			}

	// 			return &object.Float{Value: float64(sums)}

	// 		default:
	// 			return newError("Samahani, hii function haitumiki na %s", args[0].Type())
	// 		}
	// 	},
	// },
}

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)
	}
}


================================================
FILE: evaluator/builtins_wasm.go
================================================
//go:build wasm && js

// Modified version with of the builtins.go file with browser friendly versions of functions.
package evaluator

import (
	"fmt"
	"strings"
	"github.com/NuruProgramming/Nuru/object"
	"syscall/js"
)

var builtins = map[string]*object.Builtin{
	"jaza": {
		Fn: func(args ...object.Object) object.Object {

			if len(args) > 1 {
				return newError("Samahani, kiendesha hiki kinapokea hoja 0 au 1, wewe umeweka %d", len(args))
			}

			if len(args) == 1 && args[0].Type() != object.STRING_OBJ {
				return newError(fmt.Sprintf(`Tafadhali tumia alama ya nukuu: "%s"`, args[0].Inspect()))
			}

			// Get the window.prompt function
			jsPromptFunction := js.Global().Get("prompt")
			if jsPromptFunction.Type() != js.TypeFunction {
				return newError("prompt function not found")
			}

			// invoke it!!
			var result js.Value
			if len(args) == 0 {
				result = jsPromptFunction.Invoke()
			} else {
				result = jsPromptFunction.Invoke(args[0].Inspect())
			}

			if result.String() == ""|| result.String() == "null" {
				return newError("Nimeshindwa kusoma uliyo yajaza")
			}

			return &object.String{Value: string(result.String())}
		},
	},
	"andika": {
		Fn: func(args ...object.Object) object.Object {
			jsOutputReceiverFunction := js.Global().Get("nuruOutputReceiver")
			if len(args) == 0 {
				jsOutputReceiverFunction.Invoke("")
			} else {
				var arr []string
				for _, arg := range args {
					if arg == nil {
						return newError("Hauwezi kufanya operesheni hii")
					}
					arr = append(arr, arg.Inspect())
				}
				str := strings.Join(arr, " ")
				jsOutputReceiverFunction.Invoke(str) // pipe output to js land
			}
			return nil
		},
	},
}

func init(){
	for name, builtin := range commonBuiltins{
		builtins[name]=builtin
	}
}

================================================
FILE: evaluator/call.go
================================================
package evaluator

import (
	"github.com/NuruProgramming/Nuru/ast"
	"github.com/NuruProgramming/Nuru/object"
)

func evalCall(node *ast.CallExpression, env *object.Environment) object.Object {
	function := Eval(node.Function, env)

	if isError(function) {
		return function
	}

	var args []object.Object

	switch fn := function.(type) {
	case *object.Function:
		args = evalArgsExpressions(node, fn, env)
	case *object.Package:
		obj, ok := fn.Scope.Get("andaa")
		if !ok {
			return newError("Pakeji haina 'andaa'")
		}
		args = evalArgsExpressions(node, obj.(*object.Function), env)
	default:
		args = evalExpressions(node.Arguments, env)
	}

	if len(args) == 1 && isError(args[0]) {
		return args[0]
	}

	return applyFunction(function, args, node.Token.Line)
}

func evalArgsExpressions(node *ast.CallExpression, fn *object.Function, env *object.Environment) []object.Object {
	argsList := &object.Array{}
	argsHash := &object.Dict{}
	argsHash.Pairs = make(map[object.HashKey]object.DictPair)
	for _, exprr := range node.Arguments {
		switch exp := exprr.(type) {
		case *ast.Assign:
			val := Eval(exp.Value, env)
			if isError(val) {
				return []object.Object{val}
			}
			var keyHash object.HashKey
			key := &object.String{Value: exp.Name.Value}
			keyHash = key.HashKey()
			pair := object.DictPair{Key: key, Value: val}
			argsHash.Pairs[keyHash] = pair
		default:
			evaluated := Eval(exp, env)
			if isError(evaluated) {
				return []object.Object{evaluated}
			}
			argsList.Elements = append(argsList.Elements, evaluated)
		}
	}

	var result []object.Object
	var params = map[string]bool{}
	for _, exp := range fn.Parameters {
		params[exp.Value] = true
		if len(argsList.Elements) > 0 {
			result = append(result, argsList.Elements[0])
			argsList.Elements = argsList.Elements[1:]
		} else {
			keyParam := &object.String{Value: exp.Value}
			keyParamHash := keyParam.HashKey()
			if valParam, ok := argsHash.Pairs[keyParamHash]; ok {
				result = append(result, valParam.Value)
				delete(argsHash.Pairs, keyParamHash)
			} else {
				if _e, _ok := fn.Defaults[exp.Value]; _ok {
					evaluated := Eval(_e, env)
					if isError(evaluated) {
						return []object.Object{evaluated}
					}
					result = append(result, evaluated)
				} else {
					return []object.Object{&object.Error{Message: "Tumekosa Hoja"}}
				}
			}
		}
	}

	for _, pair := range argsHash.Pairs {
		if _, ok := params[pair.Key.(*object.String).Value]; ok {
			return []object.Object{&object.Error{Message: "Tumepewa hoja nyingi kwa parameter moja"}}
		}
	}

	return result

}


================================================
FILE: evaluator/dict.go
================================================
package evaluator

import (
	"github.com/NuruProgramming/Nuru/ast"
	"github.com/NuruProgramming/Nuru/object"
)

func evalDictLiteral(node *ast.DictLiteral, env *object.Environment) object.Object {
	pairs := make(map[object.HashKey]object.DictPair)

	for keyNode, valueNode := range node.Pairs {
		key := Eval(keyNode, env)
		if isError(key) {
			return key
		}

		hashKey, ok := key.(object.Hashable)
		if !ok {
			return newError("Mstari %d: Hashing imeshindikana: %s", node.Token.Line, key.Type())
		}

		value := Eval(valueNode, env)
		if isError(value) {
			return value
		}

		hashed := hashKey.HashKey()
		pairs[hashed] = object.DictPair{Key: key, Value: value}
	}

	return &object.Dict{Pairs: pairs}
}


================================================
FILE: evaluator/error_handler.go
================================================
package evaluator

import (
	"fmt"

	"github.com/NuruProgramming/Nuru/object"
)

func newError(format string, a ...interface{}) *object.Error {
	return &object.Error{Message: fmt.Sprintf(format, a...)}
}


================================================
FILE: evaluator/evaluator.go
================================================
package evaluator

import (
	"github.com/NuruProgramming/Nuru/ast"
	"github.com/NuruProgramming/Nuru/object"
)

var (
	NULL     = &object.Null{}
	TRUE     = &object.Boolean{Value: true}
	FALSE    = &object.Boolean{Value: false}
	BREAK    = &object.Break{}
	CONTINUE = &object.Continue{}
)

func Eval(node ast.Node, env *object.Environment) object.Object {
	switch node := node.(type) {
	case *ast.Program:
		return evalProgram(node, env)

	case *ast.ExpressionStatement:
		return Eval(node.Expression, env)

	case *ast.IntegerLiteral:
		return &object.Integer{Value: node.Value}

	case *ast.FloatLiteral:
		return &object.Float{Value: node.Value}

	case *ast.Boolean:
		return nativeBoolToBooleanObject(node.Value)

	case *ast.PrefixExpression:
		right := Eval(node.Right, env)
		if isError(right) {
			return right
		}
		return evalPrefixExpression(node.Operator, right, node.Token.Line)

	case *ast.InfixExpression:
		left := Eval(node.Left, env)
		if isError(left) {
			return left
		}
		right := Eval(node.Right, env)
		if isError(right) && right != nil {
			return right
		}
		return evalInfixExpression(node.Operator, left, right, node.Token.Line)
	case *ast.PostfixExpression:
		return evalPostfixExpression(env, node.Operator, node)

	case *ast.BlockStatement:
		return evalBlockStatement(node, env)

	case *ast.IfExpression:
		return evalIfExpression(node, env)

	case *ast.ReturnStatement:
		val := Eval(node.ReturnValue, env)
		if isError(val) {
			return val
		}
		return &object.ReturnValue{Value: val}

	case *ast.LetStatement:
		val := Eval(node.Value, env)
		if isError(val) {
			return val
		}

		env.Set(node.Name.Value, val)

	case *ast.Identifier:
		return evalIdentifier(node, env)

	case *ast.FunctionLiteral:
		return evalFunction(node, env)

	case *ast.MethodExpression:
		return evalMethodExpression(node, env)

	case *ast.Import:
		return evalImport(node, env)

	case *ast.CallExpression:
		return evalCall(node, env)

	case *ast.StringLiteral:
		return &object.String{Value: node.Value}
	case *ast.At:
		return evalAt(node, env)
	case *ast.ArrayLiteral:
		elements := evalExpressions(node.Elements, env)
		if len(elements) == 1 && isError(elements[0]) {
			return elements[0]
		}
		return &object.Array{Elements: elements}
	case *ast.IndexExpression:
		left := Eval(node.Left, env)
		if isError(left) {
			return left
		}
		index := Eval(node.Index, env)
		if isError(index) {
			return index
		}
		return evalIndexExpression(left, index, node.Token.Line)
	case *ast.DictLiteral:
		return evalDictLiteral(node, env)
	case *ast.WhileExpression:
		return evalWhileExpression(node, env)
	case *ast.Break:
		return evalBreak(node)
	case *ast.Continue:
		return evalContinue(node)
	case *ast.SwitchExpression:
		return evalSwitchStatement(node, env)
	case *ast.Null:
		return NULL
	// case *ast.For:
	// 	return evalForExpression(node, env)
	case *ast.ForIn:
		return evalForInExpression(node, env, node.Token.Line)
	case *ast.Package:
		return evalPackage(node, env)
	case *ast.PropertyExpression:
		return evalPropertyExpression(node, env)
	case *ast.PropertyAssignment:
		val := Eval(node.Value, env)
		if isError(val) {
			return val
		}
		return evalPropertyAssignment(node.Name, val, env)
	case *ast.Assign:
		return evalAssign(node, env)
	case *ast.AssignEqual:
		return evalAssignEqual(node, env)

	case *ast.AssignmentExpression:
		left := Eval(node.Left, env)
		if isError(left) {
			return left
		}

		value := Eval(node.Value, env)
		if isError(value) {
			return value
		}

		// This is an easy way to assign operators like +=, -= etc
		// for index expressions (arrays and dicts) where applicable
		op := node.Token.Literal
		if len(op) >= 2 {
			op = op[:len(op)-1]
			value = evalInfixExpression(op, left, value, node.Token.Line)
			if isError(value) {
				return value
			}
		}

		if ident, ok := node.Left.(*ast.Identifier); ok {
			env.Set(ident.Value, value)
		} else if ie, ok := node.Left.(*ast.IndexExpression); ok {
			obj := Eval(ie.Left, env)
			if isError(obj) {
				return obj
			}

			if array, ok := obj.(*object.Array); ok {
				index := Eval(ie.Index, env)
				if isError(index) {
					return index
				}
				if idx, ok := index.(*object.Integer); ok {
					if int(idx.Value) >= len(array.Elements) {
						return newError("Index imezidi idadi ya elements")
					}
					array.Elements[idx.Value] = value
				} else {
					return newError("Hauwezi kufanya operesheni hii na %#v", index)
				}
			} else if hash, ok := obj.(*object.Dict); ok {
				key := Eval(ie.Index, env)
				if isError(key) {
					return key
				}
				if hashKey, ok := key.(object.Hashable); ok {
					hashed := hashKey.HashKey()
					hash.Pairs[hashed] = object.DictPair{Key: key, Value: value}
				} else {
					return newError("Hauwezi kufanya operesheni hii na %T", key)
				}
			} else {
				return newError("%T haifanyi operesheni hii", obj)
			}
		} else {
			return newError("Tumia neno kama kibadala, sio %T", left)
		}

	}

	return nil
}

func evalProgram(program *ast.Program, env *object.Environment) object.Object {
	var result object.Object

	for _, statement := range program.Statements {
		result = Eval(statement, env)

		switch result := result.(type) {
		case *object.ReturnValue:
			return result.Value
		case *object.Error:
			return result
		}
	}

	return result
}

func nativeBoolToBooleanObject(input bool) *object.Boolean {
	if input {
		return TRUE
	}
	return FALSE
}

func isTruthy(obj object.Object) bool {
	switch obj {
	case NULL:
		return false
	case TRUE:
		return true
	case FALSE:
		return false
	default:
		return true
	}
}

func isError(obj object.Object) bool {
	if obj != nil {
		return obj.Type() == object.ERROR_OBJ
	}

	return false
}

func evalExpressions(exps []ast.Expression, env *object.Environment) []object.Object {
	var result []object.Object

	for _, e := range exps {
		evaluated := Eval(e, env)
		if isError(evaluated) {
			return []object.Object{evaluated}
		}

		result = append(result, evaluated)
	}

	return result
}

func applyFunction(fn object.Object, args []object.Object, line int) object.Object {
	switch fn := fn.(type) {
	case *object.Function:
		extendedEnv := extendedFunctionEnv(fn, args)
		evaluated := Eval(fn.Body, extendedEnv)
		return unwrapReturnValue(evaluated)
	case *object.Builtin:
		if result := fn.Fn(args...); result != nil {
			return result
		}
		return NULL
	case *object.Package:
		obj := &object.Instance{
			Package: fn,
			Env:     object.NewEnclosedEnvironment(fn.Env),
		}
		obj.Env.Set("@", obj)
		node, ok := fn.Scope.Get("andaa")
		if !ok {
			return newError("Hamna andaa kiendesha")
		}
		node.(*object.Function).Env.Set("@", obj)
		applyFunction(node, args, fn.Name.Token.Line)
		node.(*object.Function).Env.Del("@")
		return obj
	default:
		if fn != nil {
			return newError("Mstari %d: Hiki sio kiendesha: %s", line, fn.Type())
		} else {
			return newError("Bro how did you even get here??? Contact language maker asap!")
		}
	}

}

func extendedFunctionEnv(fn *object.Function, args []object.Object) *object.Environment {
	env := object.NewEnclosedEnvironment(fn.Env)

	for paramIdx, param := range fn.Parameters {
		if paramIdx < len(args) {
			env.Set(param.Value, args[paramIdx])
		}
	}
	return env
}

func unwrapReturnValue(obj object.Object) object.Object {
	if returnValue, ok := obj.(*object.ReturnValue); ok {
		return returnValue.Value
	}

	return obj
}

func evalBreak(node *ast.Break) object.Object {
	return BREAK
}

func evalContinue(node *ast.Continue) object.Object {
	return CONTINUE
}

// func evalForExpression(fe *ast.For, env *object.Environment) object.Object {
// 	obj, ok := env.Get(fe.Identifier)
// 	defer func() { // stay safe and not reassign an existing variable
// 		if ok {
// 			env.Set(fe.Identifier, obj)
// 		}
// 	}()
// 	val := Eval(fe.StarterValue, env)
// 	if isError(val) {
// 		return val
// 	}

// 	env.Set(fe.StarterName.Value, val)

// 	// err := Eval(fe.Starter, env)
// 	// if isError(err) {
// 	// 	return err
// 	// }
// 	for {
// 		evaluated := Eval(fe.Condition, env)
// 		if isError(evaluated) {
// 			return evaluated
// 		}
// 		if !isTruthy(evaluated) {
// 			break
// 		}
// 		res := Eval(fe.Block, env)
// 		if isError(res) {
// 			return res
// 		}
// 		if res.Type() == object.BREAK_OBJ {
// 			break
// 		}
// 		if res.Type() == object.CONTINUE_OBJ {
// 			err := Eval(fe.Closer, env)
// 			if isError(err) {
// 				return err
// 			}
// 			continue
// 		}
// 		if res.Type() == object.RETURN_VALUE_OBJ {
// 			return res
// 		}
// 		err := Eval(fe.Closer, env)
// 		if isError(err) {
// 			return err
// 		}
// 	}
// 	return NULL
// }

func loopIterable(next func() (object.Object, object.Object), env *object.Environment, fi *ast.ForIn) object.Object {
	k, v := next()
	for k != nil && v != nil {
		env.Set(fi.Key, k)
		env.Set(fi.Value, v)
		res := Eval(fi.Block, env)
		if isError(res) {
			return res
		}
		if res != nil {
			if res.Type() == object.BREAK_OBJ {
				break
			}
			if res.Type() == object.CONTINUE_OBJ {
				k, v = next()
				continue
			}
			if res.Type() == object.RETURN_VALUE_OBJ {
				return res
			}
		}
		k, v = next()
	}
	return NULL
}


================================================
FILE: evaluator/evaluator_test.go
================================================
package evaluator

import (
	"fmt"
	"testing"
	"time"

	"github.com/NuruProgramming/Nuru/lexer"
	"github.com/NuruProgramming/Nuru/object"
	"github.com/NuruProgramming/Nuru/parser"
)

func TestEvalIntegerExpression(t *testing.T) {
	tests := []struct {
		input    string
		expected int64
	}{
		{"5", 5},
		{"10", 10},
		{"-5", -5},
		{"-10", -10},
		{"5 + 5 + 5 + 5 - 10", 10},
		{"2 * 2 * 2 * 2", 16},
		{"2 / 2 + 1", 2},
	}

	for _, tt := range tests {
		evaluated := testEval(tt.input)
		testIntegerObject(t, evaluated, tt.expected)
	}
}

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
		expected bool
	}{
		{"kweli", true},
		{"sikweli", false},
		{"1 < 2", true},
		{"1 > 2", false},
		{"1 > 1", false},
		{"1 < 1", false},
		{"1 == 1", true},
		{"1 != 1", false},
		{"1 == 2", false},
		{"1 != 2", true},
		{"kweli == kweli", true},
		{"sikweli == sikweli", true},
		{"kweli == sikweli", false},
		{"kweli != sikweli", true},
		{"sikweli != kweli", true},
		{"(1 < 2) == kweli", true},
		{"!kweli", false},
		{"!sikweli", true},
		{"!tupu", true},
		{"!'kitu'", false},
		{"2 > 1 && 1 < 4", true},
		{"2 > 1 && 1 > 4", false},
		{"2 < 1 && 1 < 4", false},
		{"2 < 1 && 1 > 4", false},
		{"5 < 2 || 3 > 2", true},
		{"5 == 5 || 4 == 4", true},
		{"5 > 2 || 3 < 2", true},
		{"5 < 2 || 3 < 2", false},
		{"5 >= 2", true},
		{"5 <= 2", false},
	}

	for _, tt := range tests {
		evaluated := testEval(tt.input)
		testBooleanObject(t, evaluated, tt.expected)
	}
}

func TestBangOperator(t *testing.T) {
	tests := []struct {
		input    string
		expected bool
	}{
		{"!kweli", false},
		{"!sikweli", true},
		{"!5", false},
		{"!!kweli", true},
		{"!!sikweli", false},
		{"!!5", true},
	}

	for _, tt := range tests {
		evaluated := testEval(tt.input)
		testBooleanObject(t, evaluated, tt.expected)
	}
}

func testEval(input string) object.Object {
	l := lexer.New(input)
	p := parser.New(l)
	program := p.ParseProgram()
	env := object.NewEnvironment()

	return Eval(program, env)
}

func testIntegerObject(t *testing.T, obj object.Object, expected int64) bool {
	result, ok := obj.(*object.Integer)

	if !ok {
		t.Errorf("Object is not Integer, got=%T(%+v)", obj, obj)
		return false
	}

	if result.Value != expected {
		t.Errorf("object has wrong value. got=%d, want=%d", result.Value, expected)
		return false
	}

	return true
}

func testFloatObject(t *testing.T, obj object.Object, expected float64) bool {
	result, ok := obj.(*object.Float)

	if !ok {
		t.Errorf("Object is not Float, got=%T(%+v)", obj, obj)
		return false
	}

	if result.Value != expected {
		t.Errorf("object has wrong value. got=%f, want=%f", result.Value, expected)
		return false
	}

	return true
}

func testBooleanObject(t *testing.T, obj object.Object, expected bool) bool {
	result, ok := obj.(*object.Boolean)
	if !ok {
		t.Errorf("object is not Boolean, got=%T(%+v)", obj, obj)
		return false
	}

	if result.Value != expected {
		t.Errorf("object has wrong value, got=%t, want=%t", result.Value, expected)
		return false
	}

	return true
}

func TestIfElseExpressions(t *testing.T) {
	tests := []struct {
		input    string
		expected interface{}
	}{
		{"kama (kweli) {10}", 10},
		{"kama (sikweli) {10}", nil},
		{"kama (1) {10}", 10},
		{"kama (1 < 2) {10}", 10},
		{"kama (1 > 2) {10}", nil},
		{"kama (1 > 2) {10} sivyo {20}", 20},
		{"kama (1 < 2) {10} sivyo {20}", 10},
	}

	for _, tt := range tests {
		evaluated := testEval(tt.input)
		integer, ok := tt.expected.(int)
		if ok {
			testIntegerObject(t, evaluated, int64(integer))
		} else {
			testNullObject(t, evaluated)
		}
	}
}

func testNullObject(t *testing.T, obj object.Object) bool {
	if obj != NULL {
		t.Errorf("object is not null, got=%T(+%v)", obj, obj)
		return false
	}
	return true
}

func TestReturnStatements(t *testing.T) {
	tests := []struct {
		input    string
		expected int64
	}{
		{"rudisha 10", 10},
		{"rudisha 10; 9;", 10},
		{"rudisha 2 * 5; 9;", 10},
		{"9; rudisha 2 * 5; 9;", 10},
	}

	for _, tt := range tests {
		evaluated := testEval(tt.input)
		testIntegerObject(t, evaluated, tt.expected)
	}
}

func TestErrorHandling(t *testing.T) {
	tests := []struct {
		input           string
		expectedMessage string
	}{
		{
			"5 + kweli",
			"Mstari 1: Aina Hazilingani: NAMBA + BOOLEAN",
		},
		{
			"5 + kweli; 5;",
			"Mstari 1: Aina Hazilingani: NAMBA + BOOLEAN",
		},
		{
			"-kweli",
			"Mstari 1: Operesheni Haieleweki: -BOOLEAN",
		},
		{
			"kweli + sikweli",
			"Mstari 1: Operesheni Haieleweki: BOOLEAN + BOOLEAN",
		},
		{
			"5; kweli + sikweli; 5",
			"Mstari 1: Operesheni Haieleweki: BOOLEAN + BOOLEAN",
		},
		{
			"kama (10 > 1) { kweli + sikweli;}",
			"Mstari 1: Operesheni Haieleweki: BOOLEAN + BOOLEAN",
		},
		{
			`
kama (10 > 1) {
	kama (10 > 1) {
		rudisha kweli + kweli;
	}

	rudisha 1;
}
			`,
			"Mstari 4: Operesheni Haieleweki: BOOLEAN + BOOLEAN",
		},
		{
			"bangi",
			"Mstari 1: Neno Halifahamiki: bangi",
		},
		{
			`"Habari" - "Habari"`,
			"Mstari 1: Operesheni Haieleweki: NENO - NENO",
		},
		{
			`{"jina": "Avi"}[unda(x) {x}];`,
			"Mstari 1: Samahani, UNDO (FUNCTION) haitumiki kama ufunguo",
		},
	}

	for _, tt := range tests {
		evaluated := testEval(tt.input)

		errObj, ok := evaluated.(*object.Error)
		if !ok {
			t.Errorf("no error object return, got=%T(%+v)", evaluated, evaluated)
			continue
		}

		if errObj.Message != fmt.Sprintf(tt.expectedMessage) {
			t.Errorf("wrong error message, expected=%q, got=%q", fmt.Sprintf(tt.expectedMessage), errObj.Message)
		}
	}
}

func TestLetStatement(t *testing.T) {
	tests := []struct {
		input    string
		expected int64
	}{
		{"fanya a = 5; a;", 5},
		{"fanya a = 5 * 5; a;", 25},
		{"fanya a = 5; fanya b = a; b;", 5},
		{"fanya a = 5; fanya b = a; fanya c = a + b + 5; c;", 15},
	}

	for _, tt := range tests {
		testIntegerObject(t, testEval(tt.input), tt.expected)
	}
}

func TestFunctionObject(t *testing.T) {
	input := "unda(x) { x + 2 ;};"

	evaluated := testEval(input)
	unda, ok := evaluated.(*object.Function)
	if !ok {
		t.Fatalf("object is not a Function, got=%T(%+v)", evaluated, evaluated)
	}

	if len(unda.Parameters) != 1 {
		t.Fatalf("function has wrong parameters,Parameters=%+v", unda.Parameters)
	}

	if unda.Parameters[0].String() != "x" {
		t.Fatalf("parameter is not x, got=%q", unda.Parameters[0])
	}

	expectedBody := "(x + 2)"

	if unda.Body.String() != expectedBody {
		t.Fatalf("body is not %q, got=%q", expectedBody, unda.Body.String())
	}
}

func TestFunctionApplication(t *testing.T) {
	tests := []struct {
		input    string
		expected int64
	}{
		{"fanya mfano = unda(x) {x;}; mfano(5);", 5},
		{"fanya mfano = unda(x) {rudisha x;}; mfano(5);", 5},
		{"fanya double = unda(x) { x * 2;}; double(5);", 10},
		{"fanya add = unda(x, y) {x + y;}; add(5,5);", 10},
		{"fanya add = unda(x, y) {x + y;}; add(5 + 5, add(5, 5));", 20},
		{"unda(x) {x;}(5)", 5},
	}

	for _, tt := range tests {
		testIntegerObject(t, testEval(tt.input), tt.expected)
	}
}

func TestClosures(t *testing.T) {
	input := `
fanya newAdder = unda(x) {
	unda(y) { x + y};
};

fanya addTwo = newAdder(2);
addTwo(2);
`
	testIntegerObject(t, testEval(input), 4)
}

func TestStringLiteral(t *testing.T) {
	input := `"Habari yako!"`

	evaluated := testEval(input)
	str, ok := evaluated.(*object.String)
	if !ok {
		t.Fatalf("Object is not string, got=%T(%+v)", evaluated, evaluated)
	}

	if str.Value != "Habari yako!" {
		t.Errorf("String has wrong value, got=%q", str.Value)
	}
}

func TestStringconcatenation(t *testing.T) {
	input := `"Mambo" + " " + "Vipi" + "?"`

	evaluated := testEval(input)

	str, ok := evaluated.(*object.String)
	if !ok {
		t.Fatalf("object is not a string, got=%T(%+v)", evaluated, evaluated)
	}

	if str.Value != "Mambo Vipi?" {
		t.Errorf("String has wrong value, got=%q", str.Value)
	}
}

func TestStringMultiplyInteger(t *testing.T) {
	input := `"Mambo" * 4`

	evaluated := testEval(input)

	str, ok := evaluated.(*object.String)
	if !ok {
		t.Fatalf("object is not a string, got=%T(%+v)", evaluated, evaluated)
	}

	if str.Value != "MamboMamboMamboMambo" {
		t.Errorf("String has wrong value, got=%q", str.Value)
	}
}

// func TestBuiltinFunctions(t *testing.T) {
// 	tests := []struct {
// 		input    string
// 		expected interface{}
// 	}{
// 		{`jumla()`, "Hoja hazilingani, tunahitaji=1, tumepewa=0"},
// 		{`jumla("")`, "Samahani, hii function haitumiki na NENO"},
// 		{`jumla(1)`, "Samahani, hii function haitumiki na NAMBA"},
// 		{`jumla([1,2,3])`, 6},
// 		{`jumla([1,2,3.4])`, 6.4},
// 		{`jumla([1.1,2.5,3.4])`, 7},
// 		{`jumla([1.1,2.5,"q"])`, "Samahani namba tu zinahitajika"},
// 	}

// 	for _, tt := range tests {
// 		evaluated := testEval(tt.input)

// 		switch expected := tt.expected.(type) {
// 		case int:
// 			testIntegerObject(t, evaluated, int64(expected))
// 		case float64:
// 			testFloatObject(t, evaluated, float64(expected))

// 		case string:
// 			errObj, ok := evaluated.(*object.Error)
// 			if !ok {
// 				t.Errorf("Object is not Error, got=%T(%+v)", evaluated, evaluated)
// 				continue
// 			}
// 			if errObj.Message != fmt.Sprintf("\x1b[%dm%s\x1b[0m", 31, expected) {
// 				t.Errorf("Wrong eror message, expected=%q, got=%q", expected, errObj.Message)
// 			}
// 		}
// 	}
// }

func TestArrayLiterals(t *testing.T) {
	input := "[1, 2 * 2, 3 + 3]"

	evaluated := testEval(input)
	result, ok := evaluated.(*object.Array)
	if !ok {
		t.Fatalf("Object is not an Array, got=%T(%+v)", evaluated, evaluated)
	}

	if len(result.Elements) != 3 {
		t.Fatalf("Array has wrong number of elements, got=%d", len(result.Elements))
	}

	testIntegerObject(t, result.Elements[0], 1)
	testIntegerObject(t, result.Elements[1], 4)
	testIntegerObject(t, result.Elements[2], 6)
}

func TestArrayIndexExpressions(t *testing.T) {
	tests := []struct {
		input    string
		expected interface{}
	}{
		{
			"[1, 2, 3][0]",
			1,
		},
		{
			"[1, 2, 3][1]",
			2,
		},
		{
			"[1, 2, 3][2]",
			3,
		},
		{
			"fanya i = 0; [1][i];",
			1,
		},
		{
			"fanya myArr = [1, 2, 3]; myArr[2];",
			3,
		},
		{
			"[1, 2, 3][3]",
			nil,
		},
		{
			"[1, 2, 3][-1]",
			nil,
		},
	}

	for _, tt := range tests {
		evaluated := testEval(tt.input)
		integer, ok := tt.expected.(int)
		if ok {
			testIntegerObject(t, evaluated, int64(integer))
		} else {
			testNullObject(t, evaluated)
		}
	}
}

func TestDictLiterals(t *testing.T) {
	input := `fanya two = "two";
{
	"one": 10 - 9,
	two: 1 +1,
	"thr" + "ee": 6 / 2,
	4: 4,
	kweli: 5,
	sikweli: 6
}`

	evaluated := testEval(input)
	result, ok := evaluated.(*object.Dict)
	if !ok {
		t.Fatalf("Eval didn't return a dict, got=%T(%+v)", evaluated, evaluated)
	}

	expected := map[object.HashKey]int64{
		(&object.String{Value: "one"}).HashKey():   1,
		(&object.String{Value: "two"}).HashKey():   2,
		(&object.String{Value: "three"}).HashKey(): 3,
		(&object.Integer{Value: 4}).HashKey():      4,
		TRUE.HashKey():                             5,
		FALSE.HashKey():                            6,
	}

	if len(result.Pairs) != len(expected) {
		t.Fatalf("Dict has wrong number of pairs, got=%d", len(result.Pairs))
	}

	for expectedKey, expectedValue := range expected {
		pair, ok := result.Pairs[expectedKey]
		if !ok {
			t.Errorf("No pair for give key")
		}

		testIntegerObject(t, pair.Value, expectedValue)
	}
}

func TestDictIndexExpression(t *testing.T) {
	tests := []struct {
		input    string
		expected interface{}
	}{
		{
			`{"foo": 5}["foo"]`,
			5,
		},
		{
			`{"foo": 5}["bar"]`,
			nil,
		},
		{
			`fanya key = "foo"; {"foo": 5}[key]`,
			5,
		},
		{
			`{}["foo"]`,
			nil,
		},
		{
			`{5: 5}[5]`,
			5,
		},
		{
			`{kweli: 5}[kweli]`,
			5,
		},
		{
			`{sikweli: 5}[sikweli]`,
			5,
		},
	}

	for _, tt := range tests {
		evaluated := testEval(tt.input)
		integer, ok := tt.expected.(int)
		if ok {
			testIntegerObject(t, evaluated, int64(integer))
		} else {
			testNullObject(t, evaluated)
		}
	}
}

func TestPrefixInteger(t *testing.T) {
	tests := []struct {
		input    string
		expected interface{}
	}{
		{
			"-4",
			-4,
		},
		{
			"+5",
			5,
		},
	}

	for _, tt := range tests {
		evaluated := testEval(tt.input)
		integer, ok := tt.expected.(int)
		if !ok {
			t.Errorf("Object is not an integer")
		}
		testIntegerObject(t, evaluated, int64(integer))
	}
}

func TestPrefixFloat(t *testing.T) {
	tests := []struct {
		input    string
		expected interface{}
	}{
		{
			"-4.4",
			-4.4,
		},
		{
			"+5.5",
			5.5,
		},
	}

	for _, tt := range tests {
		evaluated := testEval(tt.input)
		float, ok := tt.expected.(float64)
		if !ok {
			t.Errorf("Object is not a float")
		}
		testFloatObject(t, evaluated, float)
	}
}

func TestInExpression(t *testing.T) {
	tests := []struct {
		input    string
		expected bool
	}{
		{
			"'a' ktk 'habari'",
			true,
		},
		{
			"'c' ktk 'habari'",
			false,
		},
		{
			"1 ktk [1, 2, 3]",
			true,
		},
		{
			"4 ktk [1, 2, 3]",
			false,
		},
		{
			"'a' ktk {'a': 'apple', 'b': 'banana'}",
			true,
		},
		{
			"'apple' ktk {'a': 'apple', 'b': 'banana'}",
			false,
		},
		{
			"'c' ktk {'a': 'apple', 'b': 'banana'}",
			false,
		},
	}

	for _, tt := range tests {
		evaluated := testEval(tt.input)
		testBooleanObject(t, evaluated, tt.expected)
	}
}

func TestArrayConcatenation(t *testing.T) {
	tests := []struct {
		input    string
		expected string
	}{
		{
			"['a', 'b', 'c'] + [1, 2, 3]",
			"[a, b, c, 1, 2, 3]",
		},
		{
			"[1, 2, 3] * 4",
			"[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]",
		},
		{
			"4 * [1, 2, 3]",
			"[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]",
		},
	}

	for _, tt := range tests {
		evaluated := testEval(tt.input)
		arr, ok := evaluated.(*object.Array)
		if !ok {
			t.Fatalf("Object is not an array, got=%T(%+v)", evaluated, evaluated)
		}

		if arr.Inspect() != tt.expected {
			t.Errorf("Array has wrong values, got=%s want=%s", arr.Inspect(), tt.expected)
		}
	}
}

func TestDictConcatenation(t *testing.T) {
	tests := []struct {
		input    string
		expected map[string]string
	}{
		{
			input:    "{'a': 'apple', 'b': 'banana'} + {'c': 'cat'}",
			expected: map[string]string{"a": "apple", "b": "banana", "c": "cat"},
		},
		{
			input:    "{'a':'bbb'} + {'a':'ccc'}",
			expected: map[string]string{"a": "ccc"},
		},
	}

	for _, tt := range tests {
		evaluated := testEval(tt.input)
		dict, ok := evaluated.(*object.Dict)
		if !ok {
			t.Fatalf("Object is not an dict, got=%T(%+v)", evaluated, evaluated)
		}

		if len(dict.Pairs) != len(tt.expected) {
			t.Errorf("Dictionary has wrong number of pairs, got=%d want=%d", len(dict.Pairs), len(tt.expected))
		}
	}
}

func TestPostfixExpression(t *testing.T) {
	inttests := []struct {
		input    string
		expected int64
	}{
		{
			"a=5; a++",
			6,
		},
		{
			"a=5; a--",
			4,
		},
	}

	for _, tt := range inttests {
		evaluated := testEval(tt.input)
		integer, ok := evaluated.(*object.Integer)
		if !ok {
			t.Fatalf("Object is not an integer, got=%T(%+v)", evaluated, evaluated)
		}
		testIntegerObject(t, integer, tt.expected)
	}
	floattests := []struct {
		input    string
		expected float64
	}{
		{
			"a=5.5; a++",
			6.5,
		},
		{
			"a=5.5; a--",
			4.5,
		},
	}

	for _, tt := range floattests {
		evaluated := testEval(tt.input)
		float, ok := evaluated.(*object.Float)
		if !ok {
			t.Fatalf("Object is not an float, got=%T(%+v)", evaluated, evaluated)
		}
		testFloatObject(t, float, tt.expected)
	}
}

func TestWhileLoop(t *testing.T) {
	input := `
	i = 10
	wakati (i > 0){
		i--
	}
	i
	`

	evaluated := testEval(input)
	i, ok := evaluated.(*object.Integer)
	if !ok {
		t.Fatalf("Object is not an integer, got=%T(+%v)", evaluated, evaluated)
	}

	if i.Value != 0 {
		t.Errorf("Incorrect value, want=0 got=%d", i.Value)
	}
}

func TestForLoop(t *testing.T) {
	input := `
	output = ""
	kwa i ktk "mojo" {
		output += i
	}
	output
	`
	evaluated := testEval(input)
	i, ok := evaluated.(*object.String)
	if !ok {
		t.Fatalf("Object is not a string, got=%T(+%v)", evaluated, evaluated)
	}

	if i.Value != "mojo" {
		t.Errorf("Wrong value: want=%s got=%s", "mojo", i.Value)
	}
}

func TestBreakLoop(t *testing.T) {
	input := `
	i = 0
	wakati (i < 10) {
		kama (i == 5) {
			vunja
		}
		i++
	}
	i
	`
	evaluated := testEval(input)
	i, ok := evaluated.(*object.Integer)
	if !ok {
		t.Fatalf("Object is not an integer, got=%T(+%v)", evaluated, evaluated)
	}

	if i.Value != 5 {
		t.Errorf("Wrong value: want=5, got=%d", i.Value)
	}

	input = `
	output = ""
	kwa i ktk "mojo" {
		output += i
		kama (i == 'o') {
			vunja
		}
	}
	output
	`

	evaluatedFor := testEval(input)
	j, ok := evaluatedFor.(*object.String)
	if !ok {
		t.Fatalf("Object is not a string, got=%T", evaluated)
	}

	if j.Value != "mo" {
		t.Errorf("Wrong value: want=%s, got=%s", "mo", j.Value)
	}
}

func TestContinueLoop(t *testing.T) {
	input := `
	i = 0
	wakati (i < 10) {
		i++
		kama (i == 5) {
			endelea
		}
		i++
	}
	i
	`
	evaluated := testEval(input)
	i, ok := evaluated.(*object.Integer)
	if !ok {
		t.Fatalf("Object is not an integer, got=%T(+%v)", evaluated, evaluated)
	}

	if i.Value != 11 {
		t.Errorf("Wrong value: want=11, got=%d", i.Value)
	}

	input = `
	output = ""
	kwa i ktk "mojo" {
		kama (i == 'o') {
			endelea
		}
		output += i
	}
	output
	`

	evaluatedFor := testEval(input)
	j, ok := evaluatedFor.(*object.String)
	if !ok {
		t.Fatalf("Object is not a string, got=%T", evaluated)
	}

	if j.Value != "mj" {
		t.Errorf("Wrong value: want=%s, got=%s", "mj", j.Value)
	}
}

func TestSwitchStatement(t *testing.T) {
	tests := []struct {
		input    string
		expected interface{}
	}{
		{
			`
			i = 5
			badili (i) {
				ikiwa 2 {
					output = 2
				}
				ikiwa 5 {
					output = 5
				}
				kawaida {
					output = "haijulikani"
				}
			}
			output
			`,
			5,
		},
		{
			`
			i = 5
			badili (i) {
				ikiwa 2 {
					output = 2
				}
				kawaida {
					output = "haijulikani"
				}
			}
			output
			`,
			"haijulikani",
		},
		{
			`
			i = 5
			badili (i) {
				ikiwa 5 {
					output = 5
				}
				ikiwa 2 {
					output = 2
				}
				kawaida {
					output = "haijulikani"
				}
			}
			output
			`,
			5,
		},
	}

	for _, tt := range tests {
		evaluated := testEval(tt.input)

		switch expected := tt.expected.(type) {
		case int:
			testIntegerObject(t, evaluated, int64(expected))
		case string:
			s, ok := evaluated.(*object.String)
			if !ok {
				t.Fatalf("Object is not a string, got=%T", evaluated)
			}

			if s.Value != tt.expected {
				t.Errorf("Wrong Value, want='haijulikani', got=%s", s.Value)
			}

		}
	}
}

func TestAssignEqual(t *testing.T) {
	tests := []struct {
		input    string
		expected interface{}
	}{
		{"a = 5; a += 5",
			10,
		},
		{
			"a = 5; a -= 5",
			0,
		},
		{
			"a = 5; a *= 10",
			50,
		},
		{
			"a = 100; a /= 4",
			25,
		},
		{
			`
		a = [1, 2, 3]
		a[0] += 500
		a[0]
		`,
			501,
		},
		{
			`
		a = "mambo"
		a += " vipi"
		`,
			"mambo vipi",
		},
		{
			"a = 5.5; a += 4.5",
			10.0,
		},
		{
			"a = 11.3; a -= 0.8",
			10.5,
		},
		{
			"a = 0.4; a /= 2",
			0.2,
		},
		{
			"a = 0.1; a *= 10",
			1.0,
		},
	}

	for _, tt := range tests {
		evaluated := testEval(tt.input)

		switch expected := tt.expected.(type) {
		case int:
			testIntegerObject(t, evaluated, int64(expected))
		case float64:
			testFloatObject(t, evaluated, float64(expected))
		case string:
			s, ok := evaluated.(*object.String)
			if !ok {
				t.Fatalf("Object not a string, got=%T", evaluated)
			}

			if s.Value != tt.expected {
				t.Errorf("Wrong value, want=%s, got=%s", tt.expected, s.Value)
			}
		}
	}
}

func TestStringMethods(t *testing.T) {
	tests := []struct {
		input    string
		expected interface{}
	}{
		{
			"'mambo'.idadi()",
			5,
		},
		{
			"'mambo'.herufikubwa()",
			"MAMBO",
		},
		{
			"'MaMbO'.herufindogo()",
			"mambo",
		},
		{
			"'habari'.gawa('a')",
			"[h, b, ri]",
		},
	}

	for _, tt := range tests {
		evaluated := testEval(tt.input)

		switch expected := tt.expected.(type) {
		case int:
			testIntegerObject(t, evaluated, int64(expected))
		case string:
			switch eval := evaluated.(type) {
			case *object.String:
				s, ok := evaluated.(*object.String)
				if !ok {
					t.Fatalf("Object not of type string, got=%T", eval)
				}
				if s.Value != tt.expected {
					t.Errorf("Wrong value: want=%s, got=%s", tt.expected, s.Value)
				}
			case *object.Array:
				arr, ok := evaluated.(*object.Array)
				if !ok {
					t.Fatalf("Object not of type array, got=%T", eval)
				}

				if arr.Inspect() != tt.expected {
					t.Errorf("Wrong value: want=%s, got=%s", tt.expected, arr.Inspect())
				}
			}
		}
	}
}

func TestTimeModule(t *testing.T) {
	input := `
	tumia muda
	muda.hasahivi()
	`

	evaluated := testEval(input)
	muda, ok := evaluated.(*object.Time)
	if !ok {
		t.Fatalf("Object is not a time object, got=%T", evaluated)
	}

	_, err := time.Parse("15:04:05 02-01-2006", muda.TimeValue)
	if err != nil {
		t.Errorf("Wrong time value: got=%v", err)
	}
}


================================================
FILE: evaluator/forin.go
================================================
package evaluator

import (
	"github.com/NuruProgramming/Nuru/ast"
	"github.com/NuruProgramming/Nuru/object"
)

func evalForInExpression(fie *ast.ForIn, env *object.Environment, line int) object.Object {
	iterable := Eval(fie.Iterable, env)
	existingKeyIdentifier, okk := env.Get(fie.Key) // again, stay safe
	existingValueIdentifier, okv := env.Get(fie.Value)
	defer func() { // restore them later on
		if okk {
			env.Set(fie.Key, existingKeyIdentifier)
		}
		if okv {
			env.Set(fie.Value, existingValueIdentifier)
		}
	}()
	switch i := iterable.(type) {
	case object.Iterable:
		defer func() {
			i.Reset()
		}()
		return loopIterable(i.Next, env, fie)
	default:
		return newError("Mstari %d: Huwezi kufanya operesheni hii na %s", line, i.Type())
	}
}


================================================
FILE: evaluator/function.go
================================================
package evaluator

import (
	"github.com/NuruProgramming/Nuru/ast"
	"github.com/NuruProgramming/Nuru/object"
)

func evalFunction(node *ast.FunctionLiteral, env *object.Environment) object.Object {
	function := &object.Function{
		Name:       node.Name,
		Parameters: node.Parameters,
		Defaults:   node.Defaults,
		Body:       node.Body,
		Env:        env,
	}

	return function
}


================================================
FILE: evaluator/identifier.go
================================================
package evaluator

import (
	"github.com/NuruProgramming/Nuru/ast"
	"github.com/NuruProgramming/Nuru/object"
)

func evalIdentifier(node *ast.Identifier, env *object.Environment) object.Object {
	if val, ok := env.Get(node.Value); ok {
		return val
	}
	if builtin, ok := builtins[node.Value]; ok {
		return builtin
	}

	return newError("Mstari %d: Neno Halifahamiki: %s", node.Token.Line, node.Value)
}


================================================
FILE: evaluator/if.go
================================================
package evaluator

import (
	"github.com/NuruProgramming/Nuru/ast"
	"github.com/NuruProgramming/Nuru/object"
)

func evalIfExpression(ie *ast.IfExpression, env *object.Environment) object.Object {
	condition := Eval(ie.Condition, env)

	if isError(condition) {
		return condition
	}

	if isTruthy(condition) {
		return Eval(ie.Consequence, env)
	} else if ie.Alternative != nil {
		return Eval(ie.Alternative, env)
	} else {
		return NULL
	}
}


================================================
FILE: evaluator/import.go
================================================
package evaluator

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"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

func evalImport(node *ast.Import, env *object.Environment) object.Object {
	for k, v := range node.Identifiers {
		if mod, ok := module.Mapper[v.Value]; ok {
			env.Set(k, mod)
		} else {
			return evalImportFile(k, v, env)
		}
	}
	return NULL
}

func evalImportFile(name string, ident *ast.Identifier, env *object.Environment) object.Object {
	addSearchPath("")
	filename := findFile(name)
	if filename == "" {
		return newError("Moduli %s haipo", name)
	}
	var scope *object.Environment
	scope, err := evaluateFile(filename, env)
	if err != nil {
		return err
	}
	return importFile(name, ident, env, scope)
}

func addSearchPath(path string) {
	searchPaths = append(searchPaths, path)
}

func findFile(name string) string {
	basename := fmt.Sprintf("%s.nr", name)
	for _, path := range searchPaths {
		file := filepath.Join(path, basename)
		if fileExists(file) {
			return file
		}
	}
	return ""
}

func fileExists(file string) bool {
	_, err := os.Stat(file)
	return err == nil
}

func evaluateFile(file string, env *object.Environment) (*object.Environment, object.Object) {
	source, err := os.ReadFile(file)
	if err != nil {
		return nil, &object.Error{Message: fmt.Sprintf("Tumeshindwa kufungua pakeji: %s", file)}
	}
	l := lexer.New(string(source))
	p := parser.New(l)
	program := p.ParseProgram()
	if len(p.Errors()) != 0 {
		return nil, &object.Error{Message: fmt.Sprintf("Pakeji %s ina makosa yafuatayo:\n%s", file, strings.Join(p.Errors(), "\n"))}
	}

	scope := object.NewEnvironment()
	result := Eval(program, scope)
	if isError(result) {
		return nil, result
	}
	return scope, nil
}

func importFile(name string, ident *ast.Identifier, env *object.Environment, scope *object.Environment) object.Object {
	value, ok := scope.Get(ident.Value)
	if !ok {
		return newError("%s sio pakeji", name)
	}
	env.Set(name, value)
	return NULL
}


================================================
FILE: evaluator/in.go
================================================
package evaluator

import (
	"strings"

	"github.com/NuruProgramming/Nuru/object"
)

func evalInExpression(left, right object.Object, line int) object.Object {
	switch right.(type) {
	case *object.String:
		return evalInStringExpression(left, right)
	case *object.Array:
		return evalInArrayExpression(left, right)
	case *object.Dict:
		return evalInDictExpression(left, right, line)
	default:
		return FALSE
	}
}

func evalInStringExpression(left, right object.Object) object.Object {
	if left.Type() != object.STRING_OBJ {
		return FALSE
	}
	leftVal := left.(*object.String)
	rightVal := right.(*object.String)
	found := strings.Contains(rightVal.Value, leftVal.Value)
	return nativeBoolToBooleanObject(found)
}

func evalInDictExpression(left, right object.Object, line int) object.Object {
	leftVal, ok := left.(object.Hashable)
	if !ok {
		return newError("Mstari %d: Huwezi kutumia kama 'key': %s", line, left.Type())
	}
	key := leftVal.HashKey()
	rightVal := right.(*object.Dict).Pairs
	_, ok = rightVal[key]
	return nativeBoolToBooleanObject(ok)
}

func evalInArrayExpression(left, right object.Object) object.Object {
	rightVal := right.(*object.Array)
	switch leftVal := left.(type) {
	case *object.Null:
		for _, v := range rightVal.Elements {
			if v.Type() == object.NULL_OBJ {
				return TRUE
			}
		}
	case *object.String:
		for _, v := range rightVal.Elements {
			if v.Type() == object.STRING_OBJ {
				elem := v.(*object.String)
				if elem.Value == leftVal.Value {
					return TRUE
				}
			}
		}
	case *object.Integer:
		for _, v := range rightVal.Elements {
			if v.Type() == object.INTEGER_OBJ {
				elem := v.(*object.Integer)
				if elem.Value == leftVal.Value {
					return TRUE
				}
			}
		}
	case *object.Float:
		for _, v := range rightVal.Elements {
			if v.Type() == object.FLOAT_OBJ {
				elem := v.(*object.Float)
				if elem.Value == leftVal.Value {
					return TRUE
				}
			}
		}
	}
	return FALSE
}


================================================
FILE: evaluator/index.go
================================================
package evaluator

import "github.com/NuruProgramming/Nuru/object"

func evalIndexExpression(left, index object.Object, line int) object.Object {
	switch {
	case left.Type() == object.ARRAY_OBJ && index.Type() == object.INTEGER_OBJ:
		return evalArrayIndexExpression(left, index)
	case left.Type() == object.ARRAY_OBJ && index.Type() != object.INTEGER_OBJ:
		return newError("Mstari %d: Tafadhali tumia number, sio: %s", line, index.Type())
	case left.Type() == object.DICT_OBJ:
		return evalDictIndexExpression(left, index, line)
	default:
		return newError("Mstari %d: Operesheni hii haiwezekani kwa: %s", line, left.Type())
	}
}

func evalArrayIndexExpression(array, index object.Object) object.Object {
	arrayObject := array.(*object.Array)
	idx := index.(*object.Integer).Value
	max := int64(len(arrayObject.Elements) - 1)

	if idx < 0 || idx > max {
		return NULL
	}

	return arrayObject.Elements[idx]
}

func evalDictIndexExpression(dict, index object.Object, line int) object.Object {
	dictObject := dict.(*object.Dict)

	key, ok := index.(object.Hashable)
	if !ok {
		return newError("Mstari %d: Samahani, %s haitumiki kama ufunguo", line, index.Type())
	}

	pair, ok := dictObject.Pairs[key.HashKey()]
	if !ok {
		return NULL
	}

	return pair.Value
}


================================================
FILE: evaluator/infix.go
================================================
package evaluator

import (
	"math"
	"strings"

	"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)
	}
	switch {

	case operator == "ktk":
		return evalInExpression(left, right, line)

	case left.Type() == object.STRING_OBJ && right.Type() == object.STRING_OBJ:
		return evalStringInfixExpression(operator, left, right, line)

	case operator == "+" && left.Type() == object.DICT_OBJ && right.Type() == object.DICT_OBJ:
		leftVal := left.(*object.Dict).Pairs
		rightVal := right.(*object.Dict).Pairs
		pairs := make(map[object.HashKey]object.DictPair)
		for k, v := range leftVal {
			pairs[k] = v
		}
		for k, v := range rightVal {
			pairs[k] = v
		}
		return &object.Dict{Pairs: pairs}

	case operator == "+" && left.Type() == object.ARRAY_OBJ && right.Type() == object.ARRAY_OBJ:
		leftVal := left.(*object.Array).Elements
		rightVal := right.(*object.Array).Elements
		elements := append(leftVal, rightVal...)
		return &object.Array{Elements: elements}

	case operator == "*" && left.Type() == object.ARRAY_OBJ && right.Type() == object.INTEGER_OBJ:
		leftVal := left.(*object.Array).Elements
		rightVal := int(right.(*object.Integer).Value)
		elements := leftVal
		for i := rightVal; i > 1; i-- {
			elements = append(elements, leftVal...)
		}
		return &object.Array{Elements: elements}

	case operator == "*" && left.Type() == object.INTEGER_OBJ && right.Type() == object.ARRAY_OBJ:
		leftVal := int(left.(*object.Integer).Value)
		rightVal := right.(*object.Array).Elements
		elements := rightVal
		for i := leftVal; i > 1; i-- {
			elements = append(elements, rightVal...)
		}
		return &object.Array{Elements: elements}

	case operator == "*" && left.Type() == object.STRING_OBJ && right.Type() == object.INTEGER_OBJ:
		leftVal := left.(*object.String).Value
		rightVal := right.(*object.Integer).Value
		return &object.String{Value: strings.Repeat(leftVal, int(rightVal))}

	case operator == "*" && left.Type() == object.INTEGER_OBJ && right.Type() == object.STRING_OBJ:
		leftVal := left.(*object.Integer).Value
		rightVal := right.(*object.String).Value
		return &object.String{Value: strings.Repeat(rightVal, int(leftVal))}

	case left.Type() == object.INTEGER_OBJ && right.Type() == object.INTEGER_OBJ:
		return evalIntegerInfixExpression(operator, left, right, line)

	case left.Type() == object.FLOAT_OBJ && right.Type() == object.FLOAT_OBJ:
		return evalFloatInfixExpression(operator, left, right, line)

	case left.Type() == object.INTEGER_OBJ && right.Type() == object.FLOAT_OBJ:
		return evalFloatIntegerInfixExpression(operator, left, right, line)

	case left.Type() == object.FLOAT_OBJ && right.Type() == object.INTEGER_OBJ:
		return evalFloatIntegerInfixExpression(operator, left, right, line)

	case operator == "==":
		return nativeBoolToBooleanObject(left == right)

	case operator == "!=":
		return nativeBoolToBooleanObject(left != right)
	case left.Type() == object.BOOLEAN_OBJ && right.Type() == object.BOOLEAN_OBJ:
		return evalBooleanInfixExpression(operator, left, right, line)

	case left.Type() != right.Type():
		return newError("Mstari %d: Aina Hazilingani: %s %s %s",
			line, left.Type(), operator, right.Type())

	default:
		return newError("Mstari %d: Operesheni Haieleweki: %s %s %s",
			line, left.Type(), operator, right.Type())
	}
}

func evalFloatIntegerInfixExpression(operator string, left, right object.Object, line int) object.Object {
	var leftVal, rightVal float64
	if left.Type() == object.FLOAT_OBJ {
		leftVal = left.(*object.Float).Value
		rightVal = float64(right.(*object.Integer).Value)
	} else {
		leftVal = float64(left.(*object.Integer).Value)
		rightVal = right.(*object.Float).Value
	}

	var val float64
	switch operator {
	case "+":
		val = leftVal + rightVal
	case "-":
		val = leftVal - rightVal
	case "*":
		val = leftVal * rightVal
	case "**":
		val = math.Pow(float64(leftVal), float64(rightVal))
	case "/":
		val = leftVal / rightVal
	case "%":
		val = math.Mod(leftVal, rightVal)
	case "<":
		return nativeBoolToBooleanObject(leftVal < rightVal)
	case "<=":
		return nativeBoolToBooleanObject(leftVal <= rightVal)
	case ">":
		return nativeBoolToBooleanObject(leftVal > rightVal)
	case ">=":
		return nativeBoolToBooleanObject(leftVal >= rightVal)
	case "==":
		return nativeBoolToBooleanObject(leftVal == rightVal)
	case "!=":
		return nativeBoolToBooleanObject(leftVal != rightVal)
	default:
		return newError("Mstari %d: Operesheni Haieleweki: %s %s %s",
			line, left.Type(), operator, right.Type())
	}

	if math.Mod(val, 1) == 0 {
		return &object.Integer{Value: int64(val)}
	} else {
		return &object.Float{Value: val}
	}
}

func evalStringInfixExpression(operator string, left, right object.Object, line int) object.Object {

	leftVal := left.(*object.String).Value
	rightVal := right.(*object.String).Value

	switch operator {
	case "+":
		return &object.String{Value: leftVal + rightVal}
	case "==":
		return nativeBoolToBooleanObject(leftVal == rightVal)
	case "!=":
		return nativeBoolToBooleanObject(leftVal != rightVal)
	default:
		return newError("Mstari %d: Operesheni Haieleweki: %s %s %s", line, left.Type(), operator, right.Type())
	}
}

func evalBooleanInfixExpression(operator string, left, right object.Object, line int) object.Object {
	leftVal := left.(*object.Boolean).Value
	rightVal := right.(*object.Boolean).Value

	switch operator {
	case "&&":
		return nativeBoolToBooleanObject(leftVal && rightVal)
	case "||":
		return nativeBoolToBooleanObject(leftVal || rightVal)
	default:
		return newError("Mstari %d: Operesheni Haieleweki: %s %s %s", line, left.Type(), operator, right.Type())
	}
}

func evalFloatInfixExpression(operator string, left, right object.Object, line int) object.Object {
	leftVal := left.(*object.Float).Value
	rightVal := right.(*object.Float).Value

	switch operator {
	case "+":
		return &object.Float{Value: leftVal + rightVal}
	case "-":
		return &object.Float{Value: leftVal - rightVal}
	case "*":
		return &object.Float{Value: leftVal * rightVal}
	case "**":
		return &object.Float{Value: math.Pow(float64(leftVal), float64(rightVal))}
	case "/":
		return &object.Float{Value: leftVal / rightVal}
	case "<":
		return nativeBoolToBooleanObject(leftVal < rightVal)
	case "<=":
		return nativeBoolToBooleanObject(leftVal <= rightVal)
	case ">":
		return nativeBoolToBooleanObject(leftVal > rightVal)
	case ">=":
		return nativeBoolToBooleanObject(leftVal >= rightVal)
	case "==":
		return nativeBoolToBooleanObject(leftVal == rightVal)
	case "!=":
		return nativeBoolToBooleanObject(leftVal != rightVal)
	default:
		return newError("Mstari %d: Operesheni Haieleweki: %s %s %s",
			line, left.Type(), operator, right.Type())
	}
}

func evalIntegerInfixExpression(operator string, left, right object.Object, line int) object.Object {
	leftVal := left.(*object.Integer).Value
	rightVal := right.(*object.Integer).Value

	switch operator {
	case "+":
		return &object.Integer{Value: leftVal + rightVal}
	case "-":
		return &object.Integer{Value: leftVal - rightVal}
	case "*":
		return &object.Integer{Value: leftVal * rightVal}
	case "**":
		return &object.Float{Value: float64(math.Pow(float64(leftVal), float64(rightVal)))}
	case "/":
		x := float64(leftVal) / float64(rightVal)
		if math.Mod(x, 1) == 0 {
			return &object.Integer{Value: int64(x)}
		} else {
			return &object.Float{Value: x}
		}
	case "%":
		return &object.Integer{Value: leftVal % rightVal}
	case "<":
		return nativeBoolToBooleanObject(leftVal < rightVal)
	case "<=":
		return nativeBoolToBooleanObject(leftVal <= rightVal)
	case ">":
		return nativeBoolToBooleanObject(leftVal > rightVal)
	case ">=":
		return nativeBoolToBooleanObject(leftVal >= rightVal)
	case "==":
		return nativeBoolToBooleanObject(leftVal == rightVal)
	case "!=":
		return nativeBoolToBooleanObject(leftVal != rightVal)
	default:
		return newError("Mstari %d: Operesheni Haieleweki: %s %s %s",
			line, left.Type(), operator, right.Type())
	}
}


================================================
FILE: evaluator/method.go
================================================
package evaluator

import (
	"github.com/NuruProgramming/Nuru/ast"
	"github.com/NuruProgramming/Nuru/object"
)

func evalMethodExpression(node *ast.MethodExpression, env *object.Environment) object.Object {
	obj := Eval(node.Object, env)
	if isError(obj) {
		return obj
	}
	args := evalExpressions(node.Arguments, env)
	if len(args) == 1 && isError(args[0]) {
		return args[0]
	}

	defs := make(map[string]object.Object)

	for k, v := range node.Defaults {
		defs[k] = Eval(v, env)
	}
	return applyMethod(obj, node.Method, args, defs, node.Token.Line)
}

func applyMethod(obj object.Object, method ast.Expression, args []object.Object, defs map[string]object.Object, l int) object.Object {
	switch obj := obj.(type) {
	case *object.String:
		return obj.Method(method.(*ast.Identifier).Value, args)
	case *object.File:
		return obj.Method(method.(*ast.Identifier).Value, args)
	case *object.Time:
		return obj.Method(method.(*ast.Identifier).Value, args, defs)
	case *object.Array:
		switch method.(*ast.Identifier).Value {
		case "map":
			return maap(obj, args)
		case "chuja":
			return filter(obj, args)
		default:
			return obj.Method(method.(*ast.Identifier).Value, args)
		}
	case *object.Module:
		if fn, ok := obj.Functions[method.(*ast.Identifier).Value]; ok {
			return fn(args, defs)
		}
	case *object.Instance:
		if fn, ok := obj.Package.Scope.Get(method.(*ast.Identifier).Value); ok {
			fn.(*object.Function).Env.Set("@", obj)
			ret := applyFunction(fn, args, l)
			fn.(*object.Function).Env.Del("@")
			return ret
		}
	case *object.Package:
		if fn, ok := obj.Scope.Get(method.(*ast.Identifier).Value); ok {
			fn.(*object.Function).Env.Set("@", obj)
			ret := applyFunction(fn, args, l)
			fn.(*object.Function).Env.Del("@")
			return ret
		}
	}
	return newError("Samahani, %s haina function '%s()'", obj.Inspect(), method.(*ast.Identifier).Value)
}

// ///////////////////////////////////////////////////////////////
// //////// Some methods here because of loop dependency ////////
// /////////////////////////////////////////////////////////////
func maap(a *object.Array, args []object.Object) object.Object {
	if len(args) != 1 && args[0].Type() != object.FUNCTION_OBJ {
		return newError("Samahani, hoja sii sahihi")
	}

	fn, ok := args[0].(*object.Function)
	if !ok {
		return newError("Samahani, hoja sii sahihi")
	}
	env := object.NewEnvironment()
	newArr := object.Array{Elements: []object.Object{}}
	for _, obj := range a.Elements {
		env.Set(fn.Parameters[0].Value, obj)
		r := Eval(fn.Body, env)
		if o, ok := r.(*object.ReturnValue); ok {
			r = o.Value
		}
		newArr.Elements = append(newArr.Elements, r)
	}
	return &newArr
}

func filter(a *object.Array, args []object.Object) object.Object {
	if len(args) != 1 && args[0].Type() != object.FUNCTION_OBJ {
		return newError("Samahani, hoja sii sahihi")
	}

	fn, ok := args[0].(*object.Function)
	if !ok {
		return newError("Samahani, hoja sii sahihi")
	}
	env := object.NewEnvironment()
	newArr := object.Array{Elements: []object.Object{}}
	for _, obj := range a.Elements {
		env.Set(fn.Parameters[0].Value, obj)
		cond := Eval(fn.Body, env)
		if cond.Inspect() == "kweli" {
			newArr.Elements = append(newArr.Elements, obj)
		}
	}
	return &newArr
}


================================================
FILE: evaluator/package.go
================================================
package evaluator

import (
	"github.com/NuruProgramming/Nuru/ast"
	"github.com/NuruProgramming/Nuru/object"
)

func evalPackage(node *ast.Package, env *object.Environment) object.Object {
	pakeji := &object.Package{
		Name:  node.Name,
		Env:   env,
		Scope: object.NewEnclosedEnvironment(env),
	}

	Eval(node.Block, pakeji.Scope)
	env.Set(node.Name.Value, pakeji)
	return pakeji
}


================================================
FILE: evaluator/postfix.go
================================================
package evaluator

import (
	"github.com/NuruProgramming/Nuru/ast"
	"github.com/NuruProgramming/Nuru/object"
)

func evalPostfixExpression(env *object.Environment, operator string, node *ast.PostfixExpression) object.Object {
	val, ok := env.Get(node.Token.Literal)
	if !ok {
		return newError("Tumia KITAMBULISHI CHA NAMBA AU DESIMALI, sio %s", node.Token.Type)
	}
	switch operator {
	case "++":
		switch arg := val.(type) {
		case *object.Integer:
			v := arg.Value + 1
			return env.Set(node.Token.Literal, &object.Integer{Value: v})
		case *object.Float:
			v := arg.Value + 1
			return env.Set(node.Token.Literal, &object.Float{Value: v})
		default:
			return newError("Mstari %d: %s sio kitambulishi cha namba. Tumia '++' na kitambulishi cha namba au desimali.\nMfano:\tfanya i = 2; i++", node.Token.Line, node.Token.Literal)

		}
	case "--":
		switch arg := val.(type) {
		case *object.Integer:
			v := arg.Value - 1
			return env.Set(node.Token.Literal, &object.Integer{Value: v})
		case *object.Float:
			v := arg.Value - 1
			return env.Set(node.Token.Literal, &object.Float{Value: v})
		default:
			return newError("Mstari %d: %s sio kitambulishi cha namba. Tumia '--' na kitambulishi cha namba au desimali.\nMfano:\tfanya i = 2; i++", node.Token.Line, node.Token.Literal)
		}
	default:
		return newError("Haifahamiki: %s", operator)
	}
}


================================================
FILE: evaluator/prefix.go
================================================
package evaluator

import "github.com/NuruProgramming/Nuru/object"

func evalMinusPrefixOperatorExpression(right object.Object, line int) object.Object {
	switch obj := right.(type) {

	case *object.Integer:
		return &object.Integer{Value: -obj.Value}

	case *object.Float:
		return &object.Float{Value: -obj.Value}

	default:
		return newError("Mstari %d: Operesheni Haieleweki: -%s", line, right.Type())
	}
}
func evalPlusPrefixOperatorExpression(right object.Object, line int) object.Object {
	switch obj := right.(type) {

	case *object.Integer:
		return &object.Integer{Value: obj.Value}

	case *object.Float:
		return &object.Float{Value: obj.Value}

	default:
		return newError("Mstari %d: Operesheni Haieleweki: +%s", line, right.Type())
	}
}

func evalPrefixExpression(operator string, right object.Object, line int) object.Object {
	switch operator {
	case "!":
		return evalBangOperatorExpression(right)
	case "-":
		return evalMinusPrefixOperatorExpression(right, line)
	case "+":
		return evalPlusPrefixOperatorExpression(right, line)
	default:
		return newError("Mstari %d: Operesheni Haieleweki: %s%s", line, operator, right.Type())
	}
}


================================================
FILE: evaluator/property.go
================================================
package evaluator

import (
	"github.com/NuruProgramming/Nuru/ast"
	"github.com/NuruProgramming/Nuru/object"
)

func evalPropertyExpression(node *ast.PropertyExpression, env *object.Environment) object.Object {
	left := Eval(node.Object, env)
	if isError(left) {
		return left
	}
	switch left.(type) {
	case *object.Instance:
		obj := left.(*object.Instance)
		prop := node.Property.(*ast.Identifier).Value
		if val, ok := obj.Env.Get(prop); ok {
			return val
		}
	case *object.Package:
		obj := left.(*object.Package)
		prop := node.Property.(*ast.Identifier).Value
		if val, ok := obj.Env.Get(prop); ok {
			return val
		}
		// case *object.Module:
		// 	mod := left.(*object.Module)
		// 	prop := node.Property.(*ast.Identifier).Value
		// 	if val, ok := mod.Properties[prop]; ok {
		// 		return val()
		// 	}
	}
	return newError("Value %s sii sahihi kwenye %s", node.Property.(*ast.Identifier).Value, left.Inspect())
}

func evalPropertyAssignment(name *ast.PropertyExpression, val object.Object, env *object.Environment) object.Object {
	left := Eval(name.Object, env)
	if isError(left) {
		return left
	}
	switch left.(type) {
	case *object.Instance:
		obj := left.(*object.Instance)
		prop := name.Property.(*ast.Identifier).Value
		if _, ok := obj.Env.Get(prop); ok {
			obj.Env.Set(prop, val)
			return NULL
		}
		obj.Env.Set(prop, val)
		return NULL
	case *object.Package:
		obj := left.(*object.Package)
		prop := name.Property.(*ast.Identifier).Value
		if _, ok := obj.Env.Get(prop); ok {
			obj.Env.Set(prop, val)
			return NULL
		}
		obj.Env.Set(prop, val)
		return NULL
	default:
		return newError("Imeshindikana kuweka kwenye pakiti %s", left.Type())
	}
}


================================================
FILE: evaluator/switch.go
================================================
package evaluator

import (
	"github.com/NuruProgramming/Nuru/ast"
	"github.com/NuruProgramming/Nuru/object"
)

func evalSwitchStatement(se *ast.SwitchExpression, env *object.Environment) object.Object {
	obj := Eval(se.Value, env)
	for _, opt := range se.Choices {

		if opt.Default {
			continue
		}
		for _, val := range opt.Expr {
			out := Eval(val, env)
			if obj.Type() == out.Type() && obj.Inspect() == out.Inspect() {
				blockOut := evalBlockStatement(opt.Block, env)
				return blockOut
			}
		}
	}
	for _, opt := range se.Choices {
		if opt.Default {
			out := evalBlockStatement(opt.Block, env)
			return out
		}
	}
	return nil
}


================================================
FILE: evaluator/type.go
================================================
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}
	}
}


================================================
FILE: evaluator/while.go
================================================
package evaluator

import (
	"github.com/NuruProgramming/Nuru/ast"
	"github.com/NuruProgramming/Nuru/object"
)

const MAX_ITERATIONS = 1_000_000

func evalWhileExpression(we *ast.WhileExpression, env *object.Environment) object.Object {
	var evaluated object.Object
	iterations := 0

	for {
		iterations++
		if iterations > MAX_ITERATIONS {
			return newError("mzunguko usio na mwisho umegunduliwa")
		}

		condition := Eval(we.Condition, env)
		if isError(condition) {
			return condition
		}

		if !isTruthy(condition) {
			break
		}

		evaluated = Eval(we.Consequence, env)
		if isError(evaluated) {
			return evaluated
		}

		if evaluated != nil && evaluated.Type() == object.BREAK_OBJ {
			return evaluated
		}
	}

	return evaluated
}


================================================
FILE: examples/Astart.nr
================================================
/*############ 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);

================================================
FILE: examples/example.nr
================================================
// basics

jina = "Nuru"
andika(jina) // Nuru

// lists

orodha = [1, "pili", kweli]

namba = [10, 20, 30]
jina = namba[1]  // jina is 20

namba[1] = 25

a = [1, 2, 3]
b = [4, 5, 6]
c = a + b // c is now [1, 2, 3, 4, 5, 6]

namba = [10, 20, 30]
andika(20 ktk namba)  // will print kweli

namba = [1, 2, 3, 4, 5]

kwa thamani ktk namba {
    andika(thamani)
}

majina = ["Juma", "Asha", "Haruna"]

kwa idx, jina ktk majina {
    andika(idx, "-", jina)
}

a = [1, 2, 3]
urefu = a.idadi()
andika(urefu)  // will print 3

a = [1, 2, 3]
a.sukuma("s", "g")
andika(a)  // will print [1, 2, 3, "s", "g"]

a = [1, 2, 3]
mwisho = a.yamwisho()
andika(mwisho)  // will print 3

b = []
mwisho = b.yamwisho()
andika(mwisho)  // will print tupu

andika(1 > 2) // Output: `sikweli`

andika(1 + 3 < 10) // Output: `kweli`

a = 5
b = 10
c = 15

result = (a < b) && (b < c)

kama (result) {
    andika("Both conditions are true")
} sivyo {
    andika("At least one condition is false")
}

// Output: "Both conditions are true"

andika(kweli && kweli) // Output: `kweli`

andika(kweli && sikweli) // Output: `sikweli`

andika(kweli || sikweli) // Output: `kweli`

andika(sikweli || sikweli) // Output: `sikweli`

andika(!kweli) // Output: `sikweli`

andika(!sikweli) // Output: `kweli`

namba = [1, 2, 3, 4, 5]

kwa thamani ktk namba {
    kama (thamani % 2 == 0) {
        andika(thamani, "is even")
    } sivyo {
        andika(thamani, "is odd")
    }
}
// Output:
// 1 is odd
// 2 is even
// 3 is odd
// 4 is even
// 5 is odd

salamu = unda() {
    jina = jaza("Unaitwa nani? ")
    andika("Mambo vipi", jina)
}

salamu()

aina(2) // Output: "NAMBA"
aina("Nuru") // Output: "NENO"


orodha = {"jina": "Juma", "umri": 25}

k = {
    "jina": "Juma",
    "umri": 25,
    kweli: "kweli",
    "salimu": unda(x) { andika("habari", x) },
    "sina value": tupu
}


andika(k[kweli]) // kweli
andika(k["salimu"]("Juma")) // habari Juma

k['umri'] = 30
andika(k['umri']) // 30

k["lugha"] = "Kiswahili"
andika(k["lugha"]) // Kiswahili

matunda = {"a": "apple", "b": "banana"}
mboga = {"c": "carrot", "d": "daikon"}
vyakula = matunda + mboga
andika(vyakula) // {"a": "apple", "b": "banana", "c": "carrot", "d": "daikon"}


"umri" ktk k // kweli
"urefu" ktk k // sikweli


hobby = {"a": "asili", "b": "baiskeli", "c": "chakula"}
kwa i, v ktk hobby {
    andika(i, "=>", v)
}
/* a => asili
   b => baiskeli
   c => chakula */


kwa v ktk hobby {
    andika(v)
}

/*
asili
baiskeli
chakula
*/

jina = "lugano"

kwa i ktk jina {
    andika(i)
}

kamusi = {"a": "andaa", "b": "baba"}

kwa v ktk kamusi {
    andika(v)
}


kwa k, v ktk kamusi {
    andika(k + " ni " + v)
}

kwa v ktk "mojo" {
    andika(v)
}

kwa i, v ktk "mojo" {
    andika(i, "->", v)
}

majina = ["juma", "asha", "haruna"]

kwa v ktk majina {
    andika(v)
}

kwa i, v ktk majina {
    andika(i, "-", v)
}


kwa i, v ktk "mojo" {
    kama (i == 2) {
        andika("nimevunja")
        vunja
    }
    andika(v)
}

kwa i, v ktk "mojo" {
    kama (i == 2) {
        andika("nimeruka")
        endelea
    }
    andika(v)
}

jum = unda(x, y) {
    rudisha x + y
}

jum(2, 3) // 5

salamu = unda() {
    andika("Habari yako")
}

salamu()

salamu = unda(jina) {
    andika("Habari yako", jina)
}

salamu("asha") // Habari yako asha

salimu = unda(salamu="Habari") {
    andika(salamu)
}

salimu() // Habari
salimu("Mambo") // Mambo

mfano = unda(x) {
    rudisha "nimerudi"
    andika(x)
}

mfano("x") // nimerudi


fib = unda(n) {
    kama (n <= 1) {
        rudisha n
    } sivyo {
        rudisha fib(n-1) + fib(n-2)
    }
}

andika(fib(10)) // 55

jum = unda(x) {
    rudisha unda(y) {
        rudisha x + y
    }
}

jum_x = jum(5)
andika(jum_x(3)) // 8

2 + 3 * 5 // 17

a = 2.5
b = 3/5

a + b // 2.8

i = 2.4

i++ // 3.4

i = 2

i *= 3 // 6
i /= 2 // 3
i += 100 // 103
i -= 10 // 93
i %= 90 // 3

i = -10

wakati (i < 0) {
    andika(i)
    i++
}


andika("mambo") // mambo

a = 'niaje'

andika("mambo", a) // mambo niaje

a = "habari" + " " + "yako"

andika(a) // habari yako

b = "habari"

b += " yako"

// habari yako

andika("mambo " * 4)

// mambo mambo mambo mambo

a = "habari"

a *= 4

// habarihabarihabarihabari

jina = "avicenna"

kwa i ktk jina {andika(i)}

a = "nuru"

andika(a == "nuru") // kweli

andika(a == "mambo") // sikweli

a = "mambo"
a.idadi() // 5

a = "NURU"
a.herufindogo() // nuru

a = "nuru mambo habari"
b = a.gawa()
andika(b) // ["nuru", "mambo", "habari"]

a = "nuru,mambo,habari"
b = a.gawa(",")
andika(b) // ["nuru", "mambo", "habari"]

a = 2

badili (a){
	ikiwa 3 {
		andika("a ni tatu")
	}
	ikiwa 2 {
		andika ("a ni mbili")
	}
}

badili (a) {
	ikiwa 1,2,3 {
		andika("a ni kati ya 1, 2 au 3")
	}
	ikiwa 4 {
		andika("a ni 4")
	}
}

z = 20

badili(z) {
	ikiwa 10 {
		andika("kumi")
	}
	ikiwa 30 {
		andika("thelathini")
	}
	kawaida {
		andika("ishirini")
	}
}

i = 1

wakati (i <= 5) {
	andika(i)
	i++
}

i = 1

wakati (i < 5) {
	kama (i == 3) {
		andika("nimevunja")
		vunja
	}
	andika(i)
	i++
}

i = 0

wakati (i < 5) {
	i++
	kama (i == 3) {
		andika("nimeruka")
		endelea
	}
	andika(i)
}

// using time:

tumia muda 

andika(muda.hasahivi())
andika("Tunalala")
muda.lala(2)
andika("Tumeamka")

s = muda.hasahivi()
muda.lala(2)
andika(muda.tangu(s))

andika(s.ongeza(sekunde=3, miaka=10, dakika=4))

// using file:

fail = fungua("sarufi.nr")

andika(fail.soma())

// using net and json:

tumia mtandao, jsoni
url = "https://v2.jokeapi.dev/joke/Any?type=single"

resp = mtandao.peruzi(url)

resp = jsoni.dikodi(resp)

andika(resp["joke"])


// os module

tumia os

andika(os.kimbiza("pwd"))

os.toka(0)


================================================
FILE: examples/perceptron.nr
================================================
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));


================================================
FILE: examples/reduce.nr
================================================
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))

================================================
FILE: examples/sarufi.nr
================================================
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
        }

    tokenYangu = unda() {
            rudisha @.token
        }

    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
        }
}




================================================
FILE: examples/sorting_algorithm.nr
================================================
/* 
############ Sorting Algorithm ##############
             
             By @VictorKariuki

        https://github.com/VictorKariuki

#############################################
*/

slice = unda(arr,start, end) {
    result = []
    wakati (start < end) {
        result = result + [arr[start]]
        start = start + 1
    }
    rudisha result
}

merge = unda(left, right) {
    result = []
    lLen = left.idadi()
    rLen = right.idadi()
     l = 0
     r = 0
    wakati (l < lLen && r < rLen) {
        kama (left[l] < right[r]) {
            result = result + [left[l]]
            l = l + 1
        } sivyo {
            result = result + [right[r]]
            r = r + 1
        }
    }
    andika(result)
}


mergeSort = unda(arr){
    len = arr.idadi()
    andika("arr is ", arr," of length ", len)
    kama (len < 2) {
        rudisha arr
    }
    andika("len is greater than or == to 2", len > 1)

    mid = (len / 2)
    andika("arr has a mid point of ", mid)
   
    left = slice(arr, 0, mid)
    right = slice(arr, mid, len)
    andika("left slice is ", left)
    andika("right slice is ", right)
    sortedLeft = mergeSort(left)
    sortedRight = mergeSort(right)
    andika("sortedLeft is ", sortedLeft)
    andika("sortedRight is ", sortedRight)
    rudisha merge(sortedLeft, sortedRight)
}

arr = [6, 5, 3, 1, 8, 7, 2, 4]
sortedArray = mergeSort(arr)
andika(sortedArray)


================================================
FILE: examples/sudoku_solver.nr
================================================
/*########### Backtracking Algorithm ##############
            
                By @VictorKariuki

        https://github.com/VictorKariuki

NURU program to solve Sudoku using Backtracking Algorithm

The sudoku puzzle is represented as a 2D array. The empty 
cells are represented by 0. The algorithm works by trying
out all possible numbers for an empty cell. If the number 
is valid, it is placed in the cell. If the number is invalid,
the algorithm backtracks to the previous cell and tries 
another number. The algorithm terminates when all cells 
are filled. The algorithm is implemented in the solveSudoku
function. The isValid function checks kama a number is
valid in a given cell. The printSudoku function prints
the sudoku puzzle. The solveSudoku function solves the
sudoku puzzle. The main function initializes the sudoku
puzzle and calls the solveSudoku function.

#################################################*/


fanya printing = unda(sudoku) {
    fanya row = 0
    wakati (row < 9){
        andika(sudoku[row])
        row++
    }
}

fanya sudoku = [[3, 0, 6, 5, 0, 8, 4, 0, 0],[5, 2, 0, 0, 0, 0, 0, 0, 0],[0, 8, 7, 0, 0, 0, 0, 3, 1],[0, 0, 3, 0, 1, 0, 0, 8, 0],[9, 0, 0, 8, 6, 3, 0, 0, 5],[0, 5, 0, 0, 9, 0, 6, 0, 0],[1, 3, 0, 0, 0, 0, 2, 5, 0],[0, 0, 0, 0, 0, 0, 0, 7, 4],[0, 0, 5, 2, 0, 6, 3, 0, 0]]



fanya isSafe = unda(grid, row, col, num) {
    kwa x ktk [0,1,2,3,4,5,6,7,8] {
        kama (grid[row][x] == num) {
            rudisha sikweli
        }
    }

    kwa x ktk [0,1,2,3,4,5,6,7,8] {
        kama (grid[x][col] == num) {
            rudisha sikweli
        }
    }

    fanya startRow = row - row % 3
    fanya startCol = col - col % 3

    kwa i ktk [0, 1, 2] {
        kwa j ktk [0, 1, 2] {
            kama (grid[i + startRow][j + startCol] == num) {
                rudisha sikweli
            }
        }
    }

    rudisha kweli
}

fanya solveSudoku = unda(grid, row, col) {
    kama (row == 8 && col == 9) {
        rudisha kweli
    }

    kama (col == 9) {
        row += 1
        col = 0
    }

    kama (grid[row][col] > 0) {
        rudisha solveSudoku(grid, row, col + 1)
    }

    kwa num ktk [1,2,3,4,5,6,7,8,9] {
        kama (isSafe(grid, row, col, num)) {
            grid[row][col] = num
            kama (solveSudoku(grid, row, col + 1)) {
                rudisha kweli
            }
        }

        grid[row][col] = 0
    }

    rudisha sikweli
}
andika()
andika("----- PUZZLE TO SOLVE -----")
printing(sudoku)
kama (solveSudoku(sudoku, 0, 0)){
    andika()
    andika("--------- SOLUTION --------")
    printing(sudoku)
    andika()
} sivyo {
    andika("imeshindikana")
}

================================================
FILE: extensions/README.md
================================================
# Nuru Extensions For Various Editors

## [VSCODE](./vscode/)

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.


================================================
FILE: extensions/vim/syntax/nuru.vim
================================================
" 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



================================================
FILE: extensions/vscode/CHANGELOG.md
================================================
# Change Log

All notable changes to the "nuru" extension will be documented in this file.

Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.

## [Unreleased]

- Initial release

================================================
FILE: extensions/vscode/README.md
================================================
# Nuru VSCode Extension

This is a syntax highliting extension for Nuru on vscode. It detects `.nr` and `.sw` files.

## Screenshots
<p align="center">
<img alt="Nuru Programming Language" src="assets/screenshot.png">
</p>

## How To Install

### Download From Market Place

- Simply download the Nuru Extension from VSCode Market Place

### Windows

- 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/NuruProgramming/Nuru/tree/main/extensions/vscode/nuru) and paste it in the VSCode extensions directory found in `~/.vscode/extensions`
- Restart VSCode


================================================
FILE: go.mod
================================================
module github.com/NuruProgramming/Nuru

go 1.18

require (
	github.com/AvicennaJr/GoPrompt v0.0.0-20230411215003-be2316d88e2d
	github.com/charmbracelet/bubbles v0.15.0
	github.com/charmbracelet/bubbletea v0.23.2
	github.com/charmbracelet/glamour v0.6.0
	github.com/charmbracelet/lipgloss v0.7.1
	github.com/lrstanley/bubblezone v0.0.0-20230303230241-08f906ff62a9
)

require (
	github.com/alecthomas/chroma v0.10.0 // indirect
	github.com/atotto/clipboard v0.1.4 // indirect
	github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
	github.com/aymerick/douceur v0.2.0 // indirect
	github.com/containerd/console v1.0.3 // indirect
	github.com/dlclark/regexp2 v1.4.0 // indirect
	github.com/gorilla/css v1.0.0 // indirect
	github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
	github.com/mattn/go-colorable v0.1.7 // indirect
	github.com/mattn/go-isatty v0.0.18 // indirect
	github.com/mattn/go-localereader v0.0.1 // indirect
	github.com/mattn/go-runewidth v0.0.14 // indirect
	github.com/mattn/go-tty v0.0.3 // indirect
	github.com/microcosm-cc/bluemonday v1.0.21 // indirect
	github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
	github.com/muesli/cancelreader v0.2.2 // indirect
	github.com/muesli/reflow v0.3.0 // indirect
	github.com/muesli/termenv v0.15.1 // indirect
	github.com/olekukonko/tablewriter v0.0.5 // indirect
	github.com/pkg/term v1.2.0-beta.2 // indirect
	github.com/rivo/uniseg v0.4.4 // indirect
	github.com/sahilm/fuzzy v0.1.0 // indirect
	github.com/yuin/goldmark v1.5.2 // indirect
	github.com/yuin/goldmark-emoji v1.0.1 // indirect
	golang.org/x/net v0.0.0-20221002022538-bcab6841153b // indirect
	golang.org/x/sync v0.1.0 // indirect
	golang.org/x/sys v0.7.0 // indirect
	golang.org/x/term v0.7.0 // indirect
	golang.org/x/text v0.9.0 // indirect
)


================================================
FILE: go.sum
================================================
github.com/AvicennaJr/GoPrompt v0.0.0-20230411215003-be2316d88e2d h1:H+Y1MQQXd83x0xC2MPOw+gFFozKTXgcW69bV80+/wpY=
github.com/AvicennaJr/GoPrompt v0.0.0-20230411215003-be2316d88e2d/go.mod h1:oo6I+tik505nlWIPCU2ogWMkOxoTt7A1YwQYlmlHqE8=
github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek=
github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s=
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/aymanbagabas/go-osc52 v1.0.3/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4=
github.com/aymanbagabas/go-osc52 v1.2.1/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/charmbracelet/bubbles v0.15.0 h1:c5vZ3woHV5W2b8YZI1q7v4ZNQaPetfHuoHzx+56Z6TI=
github.com/charmbracelet/bubbles v0.15.0/go.mod h1:Y7gSFbBzlMpUDR/XM9MhZI374Q+1p1kluf1uLl8iK74=
github.com/charmbracelet/bubbletea v0.23.1/go.mod h1:JAfGK/3/pPKHTnAS8JIE2u9f61BjWTQY57RbT25aMXU=
github.com/charmbracelet/bubbletea v0.23.2 h1:vuUJ9HJ7b/COy4I30e8xDVQ+VRDUEFykIjryPfgsdps=
github.com/charmbracelet/bubbletea v0.23.2/go.mod h1:FaP3WUivcTM0xOKNmhciz60M6I+weYLF76mr1JyI7sM=
github.com/charmbracelet/glamour v0.6.0 h1:wi8fse3Y7nfcabbbDuwolqTqMQPMnVPeZhDM273bISc=
github.com/charmbracelet/glamour v0.6.0/go.mod h1:taqWV4swIMMbWALc0m7AfE9JkPSU8om2538k9ITBxOc=
github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao=
github.com/charmbracelet/lipgloss v0.6.0/go.mod h1:tHh2wr34xcHjC2HCXIlGSG1jaDF0S0atAUvBMP6Ppuk=
github.com/charmbracelet/lipgloss v0.7.1 h1:17WMwi7N1b1rVWOjMT+rCh7sQkvDU75B2hbZpc5Kc1E=
github.com/charmbracelet/lipgloss v0.7.1/go.mod h1:yG0k3giv8Qj8edTCbbg6AlQ5e8KNWpFujkNawKNhE2c=
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/lrstanley/bubblezone v0.0.0-20230303230241-08f906ff62a9 h1:w7W7F0EBRNTRRy+MFNLGrhJLn2Ldzl8Ms2AtHtgFtuw=
github.com/lrstanley/bubblezone v0.0.0-20230303230241-08f906ff62a9/go.mod h1:v5lEwWaguF1o2MW/ucO0ZIA/IZymdBYJJ+2cMRLE7LU=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3mdw=
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-tty v0.0.3 h1:5OfyWorkyO7xP52Mq7tB36ajHDG5OHrmBGIS/DtakQI=
github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0=
github.com/microcosm-cc/bluemonday v1.0.21 h1:dNH3e4PSyE4vNX+KlRGHT5KrSvjeUkoNPwEORjffHJg=
github.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM=
github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
github.com/muesli/reflow v0.2.1-0.20210115123740-9e1d0d53df68/go.mod h1:Xk+z4oIWdQqJzsxyjgl3P22oYZnHdZ8FFTHAQQt5BMQ=
github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs=
github.com/muesli/termenv v0.13.0/go.mod h1:sP1+uffeLaEYpyOTb8pLCUctGcGLnoFjSn4YJK5e2bc=
github.com/muesli/termenv v0.14.0/go.mod h1:kG/pF1E7fh949Xhe156crRUrHNyK221IuGO7Ez60Uc8=
github.com/muesli/termenv v0.15.1 h1:UzuTb/+hhlBugQz28rpzey4ZuKcZ03MeKsoG7IJZIxs=
github.com/muesli/termenv v0.15.1/go.mod h1:HeAQPTzpfs016yGtA4g00CsdYnVLJvxsS4ANqrZs2sQ=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/pkg/term v1.2.0-beta.2 h1:L3y/h2jkuBVFdWiJvNfYfKmzcCnILw7mJWm2JQuMppw=
github.com/pkg/term v1.2.0-beta.2/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI=
github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.5.2 h1:ALmeCk/px5FSm1MAcFBAsVKZjDuMVj8Tm7FFIlMJnqU=
github.com/yuin/goldmark v1.5.2/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark-emoji v1.0.1 h1:ctuWEyzGBwiucEqxzwe0SOYDXPAucOrE9NQC18Wa1os=
github.com/yuin/goldmark-emoji v1.0.1/go.mod h1:2w1E6FEWLcDQkoTE+7HU6QF1F6SLlNGjRIBbIZQFqkQ=
golang.org/x/net v0.0.0-20221002022538-bcab6841153b h1:6e93nYa3hNqAvLr0pD4PN1fFS+gKzp2zAXqrnTCstqU=
golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=


================================================
FILE: lexer/lexer.go
================================================
// This will convert the sequence of characters into a sequence of tokens

package lexer

import (
	"github.com/NuruProgramming/Nuru/token"
)

type Lexer struct {
	input        []rune
	position     int
	readPosition int
	ch           rune
	line         int
}

func New(input string) *Lexer {
	l := &Lexer{input: []rune(input), line: 1}
	l.readChar()
	return l
}

func (l *Lexer) readChar() {
	if l.readPosition >= len(l.input) {
		l.ch = 0
	} else {
		l.ch = l.input[l.readPosition]
	}

	l.position = l.readPosition
	l.readPosition += 1
}

func (l *Lexer) NextToken() token.Token {
	var tok token.Token
	l.skipWhitespace()
	if l.ch == rune('/') && l.peekChar() == rune('/') {
		l.skipSingleLineComment()
		return l.NextToken()
	}
	if l.ch == rune('/') && l.peekChar() == rune('*') {
		l.skipMultiLineComment()
		return l.NextToken()
	}

	switch l.ch {
	case rune('='):
		if l.peekChar() == rune('=') {
			ch := l.ch
			l.readChar()
			tok = token.Token{Type: token.EQ, Literal: string(ch) + string(l.ch), Line: l.line}
		} else {
			tok = newToken(token.ASSIGN, l.line, l.ch)
		}
	case rune(';'):
		tok = newToken(token.SEMICOLON, l.line, l.ch)
	case rune('('):
		tok = newToken(token.LPAREN, l.line, l.ch)
	case rune(')'):
		tok = newToken(token.RPAREN, l.line, l.ch)
	case rune('{'):
		tok = newToken(token.LBRACE, l.line, l.ch)
	case rune('}'):
		tok = newToken(token.RBRACE, l.line, l.ch)
	case rune(','):
		tok = newToken(token.COMMA, l.line, l.ch)
	case rune('+'):
		if l.peekChar() == rune('=') {
			ch := l.ch
			l.readChar()
			tok = token.Token{Type: token.PLUS_ASSIGN, Line: l.line, Literal: string(ch) + string(l.ch)}
		} else if l.peekChar() == rune('+') {
			ch := l.ch
			l.readChar()
			tok = token.Token{Type: token.PLUS_PLUS, Literal: string(ch) + string(l.ch), Line: l.line}
		} else {
			tok = newToken(token.PLUS, l.line, l.ch)
		}
	case rune('-'):
		if l.peekChar() == rune('=') {
			ch := l.ch
			l.readChar()
			tok = token.Token{Type: token.MINUS_ASSIGN, Line: l.line, Literal: string(ch) + string(l.ch)}
		} else if l.peekChar() == rune('-') {
			ch := l.ch
			l.readChar()
			tok = token.Token{Type: token.MINUS_MINUS, Literal: string(ch) + string(l.ch), Line: l.line}
		} else {
			tok = newToken(token.MINUS, l.line, l.ch)
		}
	case rune('!'):
		if l.peekChar() == rune('=') {
			ch := l.ch
			l.readChar()
			tok = token.Token{Type: token.NOT_EQ, Literal: string(ch) + string(l.ch), Line: l.line}
		} else {
			tok = newToken(token.BANG, l.line, l.ch)
		}
	case rune('/'):
		if l.peekChar() == rune('=') {
			ch := l.ch
			l.readChar()
			tok = token.Token{Type: token.SLASH_ASSIGN, Line: l.line, Literal: string(ch) + string(l.ch)}
		} else {
			tok = newToken(token.SLASH, l.line, l.ch)
		}
	case rune('*'):
		if l.peekChar() == rune('=') {
			ch := l.ch
			l.readChar()
			tok = token.Token{Type: token.ASTERISK_ASSIGN, Line: l.line, Literal: string(ch) + string(l.ch)}
		} else if l.peekChar() == rune('*') {
			ch := l.ch
			l.readChar()
			tok = token.Token{Type: token.POW, Literal: string(ch) + string(l.ch), Line: l.line}
		} else {
			tok = newToken(token.ASTERISK, l.line, l.ch)
		}
	case rune('<'):
		if l.peekChar() == rune('=') {
			ch := l.ch
			l.readChar()
			tok = token.Token{Type: token.LTE, Literal: string(ch) + string(l.ch), Line: l.line}
		} else {
			tok = newToken(token.LT, l.line, l.ch)
		}
	case rune('>'):
		if l.peekChar() == rune('=') {
			ch := l.ch
			l.readChar()
			tok = token.Token{Type: token.GTE, Literal: string(ch) + string(l.ch), Line: l.line}
		} else {
			tok = newToken(token.GT, l.line, l.ch)
		}
	case rune('"'):
		tok.Type = token.STRING
		tok.Literal = l.readString()
		tok.Line = l.line
	case rune('\''):
		tok = token.Token{Type: token.STRING, Literal: l.readSingleQuoteString(), Line: l.line}
	case rune('['):
		tok = newToken(token.LBRACKET, l.line, l.ch)
	case rune(']'):
		tok = newToken(token.RBRACKET, l.line, l.ch)
	case rune(':'):
		tok = newToken(token.COLON, l.line, l.ch)
	case rune('@'):
		tok = newToken(token.AT, l.line, l.ch)
	case rune('.'):
		tok = newToken(token.DOT, l.line, l.ch)
	case rune('&'):
		if l.peekChar() == rune('&') {
			ch := l.ch
			l.readChar()
			tok = token.Token{Type: token.AND, Literal: string(ch) + string(l.ch), Line: l.line}
		}
	case rune('|'):
		if l.peekChar() == rune('|') {
			ch := l.ch
			l.readChar()
			tok = token.Token{Type: token.OR, Literal: string(ch) + string(l.ch), Line: l.line}
		}
	case rune('%'):
		if l.peekChar() == rune('=') {
			ch := l.ch
			l.readChar()
			tok = token.Token{Type: token.MODULUS_ASSIGN, Line: l.line, Literal: string(ch) + string(l.ch)}
		} 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
		tok.Line = l.line
	default:
		if isLetter(l.ch) {
			tok.Literal = l.readIdentifier()
			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
		} else {
			tok = newToken(token.ILLEGAL, l.line, l.ch)
		}
	}

	l.readChar()
	return tok
}

func newToken(tokenType token.TokenType, line int, ch rune) token.Token {
	return token.Token{Type: tokenType, Literal: string(ch), Line: line}
}

func (l *Lexer) readIdentifier() string {
	position := l.position

	for isLetter(l.ch) || isDigit(l.ch) {
		l.readChar()
	}
	return string(l.input[position:l.position])
}

func isLetter(ch rune) bool {
	return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch == '@'
}

func (l *Lexer) skipWhitespace() {
	for l.ch == ' ' || l.ch == '\t' || l.ch == '\n' || l.ch == '\r' {
		if l.ch == '\n' {
			l.line++
		}
		l.readChar()
	}
}

func isDigit(ch rune) bool {
	return '0' <= ch && ch <= '9'
}

func (l *Lexer) readNumber() string {
	position := l.position
	for isDigit(l.ch) {
		l.readChar()
	}
	return string(l.input[position:l.position])
}

func (l *Lexer) readDecimal() token.Token {
	integer := l.readNumber()
	if l.ch == '.' && isDigit(l.peekChar()) {
		l.readChar()
		fraction := l.readNumber()
		return token.Token{Type: token.FLOAT, Literal: integer + "." + fraction, Line: l.line}
	}
	return token.Token{Type: token.INT, Literal: integer, Line: l.line}
}

func (l *Lexer) peekChar() rune {
	if l.readPosition >= len(l.input) {
		return rune(0)
	} else {
		return l.input[l.readPosition]
	}
}

// func (l *Lexer) peekTwoChar() rune {
// 	if l.readPosition+1 >= len(l.input) {
// 		return rune(0)
// 	} else {
// 		return l.input[l.readPosition+1]
// 	}
// }

func (l *Lexer) skipSingleLineComment() {
	for l.ch != '\n' && l.ch != 0 {
		l.readChar()
	}
	l.skipWhitespace()
}

func (l *Lexer) skipMultiLineComment() {
	endFound := false

	for !endFound {
		if l.ch == 0 {
			endFound = true
		}

		if l.ch == '*' && l.peekChar() == '/' {
			endFound = true
			l.readChar()
		}

		l.readChar()
		l.skipWhitespace()
	}

}

func (l *Lexer) readString() string {
	var str string
	for {
		l.readChar()
		if l.ch == '"' || l.ch == 0 {
			break
		} else if l.ch == '\\' {
			switch l.peekChar() {
			case 'n':
				l.readChar()
				l.ch = '\n'
			case 'r':
				l.readChar()
				l.ch = '\r'
			case 't':
				l.readChar()
				l.ch = '\t'
			case '"':
				l.readChar()
				l.ch = '"'
			case '\\':
				l.readChar()
				l.ch = '\\'
			}
		}
		str += string(l.ch)
	}
	return str
}

func (l *Lexer) readSingleQuoteString() string {
	var str string
	for {
		l.readChar()
		if l.ch == '\'' || l.ch == 0 {
			break
		} else if l.ch == '\\' {
			switch l.peekChar() {
			case 'n':
				l.readChar()
				l.ch = '\n'
			case 'r':
				l.readChar()
				l.ch = '\r'
			case 't':
				l.readChar()
				l.ch = '\t'
			case '"':
				l.readChar()
				l.ch = '"'
			case '\\':
				l.readChar()
				l.ch = '\\'
			}
		}
		str += string(l.ch)
	}
	return str
}


================================================
FILE: lexer/lexer_test.go
================================================
package lexer

import (
	"testing"

	"github.com/NuruProgramming/Nuru/token"
)

func TestNextToken(t *testing.T) {
	input := `
	// Testing kama lex luther iko sawa
	fanya tano = 5;
	fanya kumi = 10;

	fanya jumla = unda(x, y){
	x + y;
	};

	fanya jibu = jumla(tano, kumi);

	!-/5;
	5 < 10 > 5;

	kama (5 < 10) {
		rudisha kweli;
	} sivyo {
		rudisha sikweli;
	}

	10 == 10;
	10 != 9; // Hii ni comment
	// Comment nyingine

	/*
	multiline comment
	*/

	/* multiline comment number twooooooooooo */
	5
	"bangi"
	"ba ngi"
	[1, 2];
	{"mambo": "vipi"}
	. // test dot
	tumia muda
	
	badili (a) {
		ikiwa 2 {
			andika(2)
		}
		kawaida {
			andika(0)
		}
	}
	
	tupu
	
	kwa i, v ktk j`

	tests := []struct {
		expectedType    token.TokenType
		expectedLiteral string
	}{
		{token.LET, "fanya"},
		{token.IDENT, "tano"},
		{token.ASSIGN, "="},
		{token.INT, "5"},
		{token.SEMICOLON, ";"},
		{token.LET, "fanya"},
		{token.IDENT, "kumi"},
		{token.ASSIGN, "="},
		{token.INT, "10"},
		{token.SEMICOLON, ";"},
		{token.LET, "fanya"},
		{token.IDENT, "jumla"},
		{token.ASSIGN, "="},
		{token.FUNCTION, "unda"},
		{token.LPAREN, "("},
		{token.IDENT, "x"},
		{token.COMMA, ","},
		{token.IDENT, "y"},
		{token.RPAREN, ")"},
		{token.LBRACE, "{"},
		{token.IDENT, "x"},
		{token.PLUS, "+"},
		{token.IDENT, "y"},
		{token.SEMICOLON, ";"},
		{token.RBRACE, "}"},
		{token.SEMICOLON, ";"},
		{token.LET, "fanya"},
		{token.IDENT, "jibu"},
		{token.ASSIGN, "="},
		{token.IDENT, "jumla"},
		{token.LPAREN, "("},
		{token.IDENT, "tano"},
		{token.COMMA, ","},
		{token.IDENT, "kumi"},
		{token.RPAREN, ")"},
		{token.SEMICOLON, ";"},
		{token.BANG, "!"},
		{token.MINUS, "-"},
		{token.SLASH, "/"},
		{token.INT, "5"},
		{token.SEMICOLON, ";"},
		{token.INT, "5"},
		{token.LT, "<"},
		{token.INT, "10"},
		{token.GT, ">"},
		{token.INT, "5"},
		{token.SEMICOLON, ";"},
		{token.IF, "kama"},
		{token.LPAREN, "("},
		{token.INT, "5"},
		{token.LT, "<"},
		{token.INT, "10"},
		{token.RPAREN, ")"},
		{token.LBRACE, "{"},
		{token.RETURN, "rudisha"},
		{token.TRUE, "kweli"},
		{token.SEMICOLON, ";"},
		{token.RBRACE, "}"},
		{token.ELSE, "sivyo"},
		{token.LBRACE, "{"},
		{token.RETURN, "rudisha"},
		{token.FALSE, "sikweli"},
		{token.SEMICOLON, ";"},
		{token.RBRACE, "}"},
		{token.INT, "10"},
		{token.EQ, "=="},
		{token.INT, "10"},
		{token.SEMICOLON, ";"},
		{token.INT, "10"},
		{token.NOT_EQ, "!="},
		{token.INT, "9"},
		{token.SEMICOLON, ";"},
		{token.INT, "5"},
		{token.STRING, "bangi"},
		{token.STRING, "ba ngi"},
		{token.LBRACKET, "["},
		{token.INT, "1"},
		{token.COMMA, ","},
		{token.INT, "2"},
		{token.RBRACKET, "]"},
		{token.SEMICOLON, ";"},
		{token.LBRACE, "{"},
		{token.STRING, "mambo"},
		{token.COLON, ":"},
		{token.STRING, "vipi"},
		{token.RBRACE, "}"},
		{token.DOT, "."},
		{token.IMPORT, "tumia"},
		{token.IDENT, "muda"},
		{token.SWITCH, "badili"},
		{token.LPAREN, "("},
		{token.IDENT, "a"},
		{token.RPAREN, ")"},
		{token.LBRACE, "{"},
		{token.CASE, "ikiwa"},
		{token.INT, "2"},
		{token.LBRACE, "{"},
		{token.IDENT, "andika"},
		{token.LPAREN, "("},
		{token.INT, "2"},
		{token.RPAREN, ")"},
		{token.RBRACE, "}"},
		{token.DEFAULT, "kawaida"},
		{token.LBRACE, "{"},
		{token.IDENT, "andika"},
		{token.LPAREN, "("},
		{token.INT, "0"},
		{token.RPAREN, ")"},
		{token.RBRACE, "}"},
		{token.RBRACE, "}"},
		{token.NULL, "tupu"},
		{token.FOR, "kwa"},
		{token.IDENT, "i"},
		{token.COMMA, ","},
		{token.IDENT, "v"},
		{token.IN, "ktk"},
		{token.IDENT, "j"},
		{token.EOF, ""},
	}

	l := New(input)

	for i, tt := range tests {
		tok := l.NextToken()

		if tok.Type != tt.expectedType {
			t.Fatalf("tests[%d] - tokentype wrong. expected=%q, got=%q",
				i, tt.expectedType, tok.Type)
		}

		if tok.Literal != tt.expectedLiteral {
			t.Fatalf("tests[%d] - literal wrong. expected=%q, got=%q",
				i, tt.expectedLiteral, tok.Literal)
		}
	}
}


================================================
FILE: main.go
================================================
//go:build !wasm || !js

package main

import (
	"fmt"
	"os"
	"strings"

	"github.com/NuruProgramming/Nuru/repl"
	"github.com/NuruProgramming/Nuru/styles"
	"github.com/charmbracelet/lipgloss"
)

var (
	Title = styles.TitleStyle.
		Render(`
█░░ █░█ █▀▀ █░█ ▄▀█   █▄█ ▄▀█   █▄░█ █░█ █▀█ █░█
█▄▄ █▄█ █▄█ █▀█ █▀█   ░█░ █▀█   █░▀█ █▄█ █▀▄ █▄█`)
	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
	%s: Kuendesha faili la Nuru
	%s: Kusoma nyaraka za Nuru
	%s: Kufahamu toleo la Nuru
`,
		styles.HelpStyle.Bold(true).Render("nuru"),
		styles.HelpStyle.Bold(true).Render("nuru jinaLaFile.nr"),
		styles.HelpStyle.Bold(true).Render("nuru --nyaraka"),
		styles.HelpStyle.Bold(true).Render("nuru --toleo")))
)

func main() {

	args := os.Args
	if len(args) < 2 {

		help := styles.HelpStyle.Render("💡 Tumia exit() au toka() kuondoka")
		fmt.Println(lipgloss.JoinVertical(lipgloss.Left, NewLogo, "\n", help))
		repl.Start()
		return
	}

	if len(args) == 2 {
		switch args[1] {
		case "msaada", "-msaada", "--msaada", "help", "-help", "--help", "-h":
			fmt.Println(Help)
		case "version", "-version", "--version", "-v", "v", "--toleo", "-toleo":
			fmt.Println(NewLogo)
		case "-docs", "--docs", "-nyaraka", "--nyaraka":
			repl.Docs()
		default:
			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)
				}

				repl.Read(string(contents))
			} else {
				fmt.Println(styles.ErrorStyle.Render("'"+file+"'", "sii faili sahihi. Tumia faili la '.nr' au '.sw'"))
				os.Exit(1)
			}
		}
	} else {
		fmt.Println(styles.ErrorStyle.Render("Error: Operesheni imeshindikana boss."))
		fmt.Println(Help)
		os.Exit(1)
	}
}


================================================
FILE: main_wasm.go
================================================
//go:build wasm && js

package main

import (
	"fmt"

	"github.com/NuruProgramming/Nuru/evaluator"
	"github.com/NuruProgramming/Nuru/lexer"
	"github.com/NuruProgramming/Nuru/object"
	"github.com/NuruProgramming/Nuru/parser"

	"syscall/js"
)

func Read(contents string) {
	jsOutputReceiverFunction := js.Global().Get("nuruOutputReceiver")

	env := object.NewEnvironment()

	l := lexer.New(contents)
	p := parser.New(l)

	program := p.ParseProgram()

	if len(p.Errors()) != 0 {
		fmt.Println("Kuna makosa yafuatayo:")
		jsOutputReceiverFunction.Invoke("Kuna makosa yafuatayo:", true)

		for _, msg := range p.Errors() {
			// fmt.Println("\t" + msg)
			jsOutputReceiverFunction.Invoke("\t" + msg, true)
		}

	}
	evaluated := evaluator.Eval(program, env)
	if evaluated != nil {
		if evaluated.Type() != object.NULL_OBJ {
			jsOutputReceiverFunction.Invoke(evaluated.Inspect(), true)
		}
	}

}

func runCode(this js.Value, args []js.Value) interface{} {
	code := args[0].String()
	Read(code)
	return nil
}

func main() {
	fmt.Println("Go WASM initialized")
	js.Global().Set("runCode", js.FuncOf(runCode))
	<-make(chan bool)
}


================================================
FILE: module/hisabati.go
================================================
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 {
		
Download .txt
gitextract_yf7p31zd/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.yml
│   │   └── feature-request.yml
│   ├── PULL_REQUEST_TEMPLATE
│   └── workflows/
│       ├── build.yml
│       └── tests.yml
├── .gitignore
├── .goreleaser.yaml
├── ABOUT.md
├── LICENSE
├── Makefile
├── README.md
├── ast/
│   ├── ast.go
│   └── ast_test.go
├── evaluator/
│   ├── assign.go
│   ├── assignEqual.go
│   ├── at.go
│   ├── bang.go
│   ├── block.go
│   ├── builtins.go
│   ├── builtins_common.go
│   ├── builtins_wasm.go
│   ├── call.go
│   ├── dict.go
│   ├── error_handler.go
│   ├── evaluator.go
│   ├── evaluator_test.go
│   ├── forin.go
│   ├── function.go
│   ├── identifier.go
│   ├── if.go
│   ├── import.go
│   ├── in.go
│   ├── index.go
│   ├── infix.go
│   ├── method.go
│   ├── package.go
│   ├── postfix.go
│   ├── prefix.go
│   ├── property.go
│   ├── switch.go
│   ├── type.go
│   └── while.go
├── examples/
│   ├── Astart.nr
│   ├── example.nr
│   ├── perceptron.nr
│   ├── reduce.nr
│   ├── sarufi.nr
│   ├── sorting_algorithm.nr
│   └── sudoku_solver.nr
├── extensions/
│   ├── README.md
│   ├── vim/
│   │   └── syntax/
│   │       └── nuru.vim
│   └── vscode/
│       ├── CHANGELOG.md
│       └── README.md
├── go.mod
├── go.sum
├── gotest
├── lexer/
│   ├── lexer.go
│   └── lexer_test.go
├── main.go
├── main_wasm.go
├── module/
│   ├── hisabati.go
│   ├── json.go
│   ├── module.go
│   ├── net.go
│   ├── os.go
│   └── time.go
├── object/
│   ├── array.go
│   ├── at.go
│   ├── bool.go
│   ├── break.go
│   ├── builtin.go
│   ├── byte.go
│   ├── continue.go
│   ├── dict.go
│   ├── environment.go
│   ├── error.go
│   ├── error_wasm.go
│   ├── file.go
│   ├── float.go
│   ├── function.go
│   ├── instance.go
│   ├── integer.go
│   ├── module.go
│   ├── null.go
│   ├── object.go
│   ├── object_test.go
│   ├── package.go
│   ├── return.go
│   ├── strings.go
│   └── time.go
├── parser/
│   ├── arrays.go
│   ├── assignEqual.go
│   ├── assignment.go
│   ├── at.go
│   ├── boolean.go
│   ├── break.go
│   ├── continue.go
│   ├── dict.go
│   ├── dot.go
│   ├── float.go
│   ├── for.go
│   ├── function.go
│   ├── identifier.go
│   ├── if.go
│   ├── import.go
│   ├── index.go
│   ├── integer.go
│   ├── null.go
│   ├── package.go
│   ├── parser.go
│   ├── parser_test.go
│   ├── statements.go
│   ├── string.go
│   ├── switch.go
│   └── while.go
├── repl/
│   ├── docs/
│   │   ├── en/
│   │   │   ├── README.md
│   │   │   ├── arrays.md
│   │   │   ├── bool.md
│   │   │   ├── builtins.md
│   │   │   ├── comments.md
│   │   │   ├── dictionaries.md
│   │   │   ├── files.md
│   │   │   ├── for.md
│   │   │   ├── function.md
│   │   │   ├── hisabati.md
│   │   │   ├── identifiers.md
│   │   │   ├── ifStatements.md
│   │   │   ├── json.md
│   │   │   ├── keywords.md
│   │   │   ├── net.md
│   │   │   ├── null.md
│   │   │   ├── numbers.md
│   │   │   ├── operators.md
│   │   │   ├── packages.md
│   │   │   ├── range.md
│   │   │   ├── strings.md
│   │   │   ├── switch.md
│   │   │   ├── time.md
│   │   │   └── while.md
│   │   └── sw/
│   │       ├── README.md
│   │       ├── arrays.md
│   │       ├── bools.md
│   │       ├── builtins.md
│   │       ├── dictionaries.md
│   │       ├── for.md
│   │       ├── functions.md
│   │       ├── identifiers.md
│   │       ├── if.md
│   │       ├── keywords.md
│   │       ├── maoni.md
│   │       ├── null.md
│   │       ├── numbers.md
│   │       ├── operators.md
│   │       ├── range.md
│   │       ├── strings.md
│   │       ├── switch.md
│   │       └── while.md
│   ├── docs.go
│   └── repl.go
├── sh/
│   └── install.sh
├── styles/
│   └── styles.go
├── third_party/
│   └── math/
│       ├── README.md
│       ├── hesabu.nr
│       └── test.nr
├── token/
│   └── token.go
└── upx
Download .txt
SYMBOL INDEX (654 symbols across 93 files)

FILE: ast/ast.go
  type Node (line 10) | type Node interface
  type Statement (line 15) | type Statement interface
  type Expression (line 20) | type Expression interface
  type Program (line 25) | type Program struct
    method TokenLiteral (line 29) | func (p *Program) TokenLiteral() string {
    method String (line 37) | func (p *Program) String() string {
  type LetStatement (line 47) | type LetStatement struct
    method statementNode (line 53) | func (ls *LetStatement) statementNode()       {}
    method TokenLiteral (line 54) | func (ls *LetStatement) TokenLiteral() string { return ls.Token.Literal }
    method String (line 55) | func (ls *LetStatement) String() string {
  type Identifier (line 70) | type Identifier struct
    method expressionNode (line 75) | func (i *Identifier) expressionNode()      {}
    method TokenLiteral (line 76) | func (i *Identifier) TokenLiteral() string { return i.Token.Literal }
    method String (line 77) | func (i *Identifier) String() string       { return i.Value }
  type ReturnStatement (line 79) | type ReturnStatement struct
    method statementNode (line 84) | func (rs *ReturnStatement) statementNode()       {}
    method TokenLiteral (line 85) | func (rs *ReturnStatement) TokenLiteral() string { return rs.Token.Lit...
    method String (line 86) | func (rs *ReturnStatement) String() string {
  type ExpressionStatement (line 98) | type ExpressionStatement struct
    method statementNode (line 103) | func (es *ExpressionStatement) statementNode()       {}
    method TokenLiteral (line 104) | func (es *ExpressionStatement) TokenLiteral() string { return es.Token...
    method String (line 105) | func (es *ExpressionStatement) String() string {
  type IntegerLiteral (line 113) | type IntegerLiteral struct
    method expressionNode (line 118) | func (il *IntegerLiteral) expressionNode()      {}
    method TokenLiteral (line 119) | func (il *IntegerLiteral) TokenLiteral() string { return il.Token.Lite...
    method String (line 120) | func (il *IntegerLiteral) String() string       { return il.Token.Lite...
  type PrefixExpression (line 122) | type PrefixExpression struct
    method expressionNode (line 128) | func (pe *PrefixExpression) expressionNode()      {}
    method TokenLiteral (line 129) | func (pe *PrefixExpression) TokenLiteral() string { return pe.Token.Li...
    method String (line 130) | func (pe *PrefixExpression) String() string {
  type InfixExpression (line 141) | type InfixExpression struct
    method expressionNode (line 148) | func (oe *InfixExpression) expressionNode()      {}
    method TokenLiteral (line 149) | func (oe *InfixExpression) TokenLiteral() string { return oe.Token.Lit...
    method String (line 150) | func (oe *InfixExpression) String() string {
  type Boolean (line 162) | type Boolean struct
    method expressionNode (line 167) | func (b *Boolean) expressionNode()      {}
    method TokenLiteral (line 168) | func (b *Boolean) TokenLiteral() string { return b.Token.Literal }
    method String (line 169) | func (b *Boolean) String() string       { return b.Token.Literal }
  type IfExpression (line 171) | type IfExpression struct
    method expressionNode (line 178) | func (ie *IfExpression) expressionNode()      {}
    method TokenLiteral (line 179) | func (ie *IfExpression) TokenLiteral() string { return ie.Token.Literal }
    method String (line 180) | func (ie *IfExpression) String() string {
  type BlockStatement (line 195) | type BlockStatement struct
    method statementNode (line 200) | func (bs *BlockStatement) statementNode()       {}
    method TokenLiteral (line 201) | func (bs *BlockStatement) TokenLiteral() string { return bs.Token.Lite...
    method String (line 202) | func (bs *BlockStatement) String() string {
  type FunctionLiteral (line 212) | type FunctionLiteral struct
    method expressionNode (line 220) | func (fl *FunctionLiteral) expressionNode()      {}
    method TokenLiteral (line 221) | func (fl *FunctionLiteral) TokenLiteral() string { return fl.Token.Lit...
    method String (line 222) | func (fl *FunctionLiteral) String() string {
  type CallExpression (line 240) | type CallExpression struct
    method expressionNode (line 246) | func (ce *CallExpression) expressionNode()      {}
    method TokenLiteral (line 247) | func (ce *CallExpression) TokenLiteral() string { return ce.Token.Lite...
    method String (line 248) | func (ce *CallExpression) String() string {
  type StringLiteral (line 264) | type StringLiteral struct
    method expressionNode (line 269) | func (sl *StringLiteral) expressionNode()      {}
    method TokenLiteral (line 270) | func (sl *StringLiteral) TokenLiteral() string { return sl.Token.Liter...
    method String (line 271) | func (sl *StringLiteral) String() string       { return sl.Token.Liter...
  type ArrayLiteral (line 273) | type ArrayLiteral struct
    method expressionNode (line 278) | func (al *ArrayLiteral) expressionNode()      {}
    method TokenLiteral (line 279) | func (al *ArrayLiteral) TokenLiteral() string { return al.Token.Literal }
    method String (line 280) | func (al *ArrayLiteral) String() string {
  type IndexExpression (line 295) | type IndexExpression struct
    method expressionNode (line 301) | func (ie *IndexExpression) expressionNode()      {}
    method TokenLiteral (line 302) | func (ie *IndexExpression) TokenLiteral() string { return ie.Token.Lit...
    method String (line 303) | func (ie *IndexExpression) String() string {
  type DictLiteral (line 315) | type DictLiteral struct
    method expressionNode (line 320) | func (dl *DictLiteral) expressionNode()      {}
    method TokenLiteral (line 321) | func (dl *DictLiteral) TokenLiteral() string { return dl.Token.Literal }
    method String (line 322) | func (dl *DictLiteral) String() string {
  type Assign (line 336) | type Assign struct
    method expressionNode (line 342) | func (ae *Assign) expressionNode()      {}
    method TokenLiteral (line 343) | func (ae *Assign) TokenLiteral() string { return ae.Token.Literal }
    method String (line 344) | func (ae *Assign) String() string {
  type AssignEqual (line 354) | type AssignEqual struct
    method expressionNode (line 360) | func (ae *AssignEqual) expressionNode()      {}
    method TokenLiteral (line 361) | func (ae *AssignEqual) TokenLiteral() string { return ae.Token.Literal }
    method String (line 362) | func (ae *AssignEqual) String() string {
  type AssignmentExpression (line 372) | type AssignmentExpression struct
    method expressionNode (line 378) | func (ae *AssignmentExpression) expressionNode()      {}
    method TokenLiteral (line 379) | func (ae *AssignmentExpression) TokenLiteral() string { return ae.Toke...
    method String (line 380) | func (ae *AssignmentExpression) String() string {
  type WhileExpression (line 390) | type WhileExpression struct
    method expressionNode (line 396) | func (we *WhileExpression) expressionNode()      {}
    method TokenLiteral (line 397) | func (we *WhileExpression) TokenLiteral() string { return we.Token.Lit...
    method String (line 398) | func (we *WhileExpression) String() string {
  type Null (line 409) | type Null struct
    method expressionNode (line 413) | func (n *Null) expressionNode()      {}
    method TokenLiteral (line 414) | func (n *Null) TokenLiteral() string { return n.Token.Literal }
    method String (line 415) | func (n *Null) String() string       { return n.Token.Literal }
  type Break (line 417) | type Break struct
    method expressionNode (line 422) | func (b *Break) expressionNode()      {}
    method TokenLiteral (line 423) | func (b *Break) TokenLiteral() string { return b.Token.Literal }
    method String (line 424) | func (b *Break) String() string       { return b.Token.Literal }
  type Continue (line 426) | type Continue struct
    method expressionNode (line 431) | func (c *Continue) expressionNode()      {}
    method TokenLiteral (line 432) | func (c *Continue) TokenLiteral() string { return c.Token.Literal }
    method String (line 433) | func (c *Continue) String() string       { return c.Token.Literal }
  type PostfixExpression (line 435) | type PostfixExpression struct
    method expressionNode (line 440) | func (pe *PostfixExpression) expressionNode()      {}
    method TokenLiteral (line 441) | func (pe *PostfixExpression) TokenLiteral() string { return pe.Token.L...
    method String (line 442) | func (pe *PostfixExpression) String() string {
  type FloatLiteral (line 451) | type FloatLiteral struct
    method expressionNode (line 456) | func (fl *FloatLiteral) expressionNode()      {}
    method TokenLiteral (line 457) | func (fl *FloatLiteral) TokenLiteral() string { return fl.Token.Literal }
    method String (line 458) | func (fl *FloatLiteral) String() string       { return fl.Token.Literal }
  type For (line 460) | type For struct
  type ForIn (line 470) | type ForIn struct
    method expressionNode (line 478) | func (fi *ForIn) expressionNode()      {}
    method TokenLiteral (line 479) | func (fi *ForIn) TokenLiteral() string { return fi.Token.Literal }
    method String (line 480) | func (fi *ForIn) String() string {
  type CaseExpression (line 496) | type CaseExpression struct
    method expressionNode (line 503) | func (ce *CaseExpression) expressionNode()      {}
    method TokenLiteral (line 504) | func (ce *CaseExpression) TokenLiteral() string { return ce.Token.Lite...
    method String (line 505) | func (ce *CaseExpression) String() string {
  type SwitchExpression (line 523) | type SwitchExpression struct
    method expressionNode (line 529) | func (se *SwitchExpression) expressionNode()      {}
    method TokenLiteral (line 530) | func (se *SwitchExpression) TokenLiteral() string { return se.Token.Li...
    method String (line 531) | func (se *SwitchExpression) String() string {
  type MethodExpression (line 547) | type MethodExpression struct
    method expressionNode (line 555) | func (me *MethodExpression) expressionNode()      {}
    method TokenLiteral (line 556) | func (me *MethodExpression) TokenLiteral() string { return me.Token.Li...
    method String (line 557) | func (me *MethodExpression) String() string {
  type Import (line 566) | type Import struct
    method expressionNode (line 571) | func (i *Import) expressionNode()      {}
    method TokenLiteral (line 572) | func (i *Import) TokenLiteral() string { return i.Token.Literal }
    method String (line 573) | func (i *Import) String() string {
  type PackageBlock (line 582) | type PackageBlock struct
    method statementNode (line 587) | func (pb *PackageBlock) statementNode()       {}
    method TokenLiteral (line 588) | func (pb *PackageBlock) TokenLiteral() string { return pb.Token.Literal }
    method String (line 589) | func (pb *PackageBlock) String() string {
  type Package (line 599) | type Package struct
    method expressionNode (line 605) | func (p *Package) expressionNode()      {}
    method TokenLiteral (line 606) | func (p *Package) TokenLiteral() string { return p.Token.Literal }
    method String (line 607) | func (p *Package) String() string {
  type At (line 620) | type At struct
    method expressionNode (line 624) | func (a *At) expressionNode()      {}
    method TokenLiteral (line 625) | func (a *At) TokenLiteral() string { return a.Token.Literal }
    method String (line 626) | func (a *At) String() string       { return "@" }
  type PropertyAssignment (line 628) | type PropertyAssignment struct
    method expressionNode (line 634) | func (pa *PropertyAssignment) expressionNode()      {}
    method TokenLiteral (line 635) | func (pa *PropertyAssignment) TokenLiteral() string { return pa.Token....
    method String (line 636) | func (pa *PropertyAssignment) String() string       { return "Ngl I'm ...
  type PropertyExpression (line 638) | type PropertyExpression struct
    method expressionNode (line 645) | func (pe *PropertyExpression) expressionNode()      {}
    method TokenLiteral (line 646) | func (pe *PropertyExpression) TokenLiteral() string { return pe.Token....
    method String (line 647) | func (pe *PropertyExpression) String() string       { return "Ngl I'm ...

FILE: ast/ast_test.go
  function TestString (line 9) | func TestString(t *testing.T) {

FILE: evaluator/assign.go
  function evalAssign (line 8) | func evalAssign(node *ast.Assign, env *object.Environment) object.Object {

FILE: evaluator/assignEqual.go
  function evalAssignEqual (line 10) | func evalAssignEqual(node *ast.AssignEqual, env *object.Environment) obj...

FILE: evaluator/at.go
  function evalAt (line 8) | func evalAt(node *ast.At, env *object.Environment) object.Object {

FILE: evaluator/bang.go
  function evalBangOperatorExpression (line 5) | func evalBangOperatorExpression(right object.Object) object.Object {

FILE: evaluator/block.go
  function evalBlockStatement (line 8) | func evalBlockStatement(block *ast.BlockStatement, env *object.Environme...

FILE: evaluator/builtins.go
  function init (line 79) | func init(){

FILE: evaluator/builtins_common.go
  function getIntValue (line 194) | func getIntValue(obj object.Object) (int64, error) {

FILE: evaluator/builtins_wasm.go
  function init (line 67) | func init(){

FILE: evaluator/call.go
  function evalCall (line 8) | func evalCall(node *ast.CallExpression, env *object.Environment) object....
  function evalArgsExpressions (line 37) | func evalArgsExpressions(node *ast.CallExpression, fn *object.Function, ...

FILE: evaluator/dict.go
  function evalDictLiteral (line 8) | func evalDictLiteral(node *ast.DictLiteral, env *object.Environment) obj...

FILE: evaluator/error_handler.go
  function newError (line 9) | func newError(format string, a ...interface{}) *object.Error {

FILE: evaluator/evaluator.go
  function Eval (line 16) | func Eval(node ast.Node, env *object.Environment) object.Object {
  function evalProgram (line 206) | func evalProgram(program *ast.Program, env *object.Environment) object.O...
  function nativeBoolToBooleanObject (line 223) | func nativeBoolToBooleanObject(input bool) *object.Boolean {
  function isTruthy (line 230) | func isTruthy(obj object.Object) bool {
  function isError (line 243) | func isError(obj object.Object) bool {
  function evalExpressions (line 251) | func evalExpressions(exps []ast.Expression, env *object.Environment) []o...
  function applyFunction (line 266) | func applyFunction(fn object.Object, args []object.Object, line int) obj...
  function extendedFunctionEnv (line 301) | func extendedFunctionEnv(fn *object.Function, args []object.Object) *obj...
  function unwrapReturnValue (line 312) | func unwrapReturnValue(obj object.Object) object.Object {
  function evalBreak (line 320) | func evalBreak(node *ast.Break) object.Object {
  function evalContinue (line 324) | func evalContinue(node *ast.Continue) object.Object {
  function loopIterable (line 379) | func loopIterable(next func() (object.Object, object.Object), env *objec...

FILE: evaluator/evaluator_test.go
  function TestEvalIntegerExpression (line 13) | func TestEvalIntegerExpression(t *testing.T) {
  function TestEvalFloatExpression (line 33) | func TestEvalFloatExpression(t *testing.T) {
  function TestEvalBooleanExpression (line 47) | func TestEvalBooleanExpression(t *testing.T) {
  function TestBangOperator (line 90) | func TestBangOperator(t *testing.T) {
  function testEval (line 109) | func testEval(input string) object.Object {
  function testIntegerObject (line 118) | func testIntegerObject(t *testing.T, obj object.Object, expected int64) ...
  function testFloatObject (line 134) | func testFloatObject(t *testing.T, obj object.Object, expected float64) ...
  function testBooleanObject (line 150) | func testBooleanObject(t *testing.T, obj object.Object, expected bool) b...
  function TestIfElseExpressions (line 165) | func TestIfElseExpressions(t *testing.T) {
  function testNullObject (line 190) | func testNullObject(t *testing.T, obj object.Object) bool {
  function TestReturnStatements (line 198) | func TestReturnStatements(t *testing.T) {
  function TestErrorHandling (line 215) | func TestErrorHandling(t *testing.T) {
  function TestLetStatement (line 285) | func TestLetStatement(t *testing.T) {
  function TestFunctionObject (line 301) | func TestFunctionObject(t *testing.T) {
  function TestFunctionApplication (line 325) | func TestFunctionApplication(t *testing.T) {
  function TestClosures (line 343) | func TestClosures(t *testing.T) {
  function TestStringLiteral (line 355) | func TestStringLiteral(t *testing.T) {
  function TestStringconcatenation (line 369) | func TestStringconcatenation(t *testing.T) {
  function TestStringMultiplyInteger (line 384) | func TestStringMultiplyInteger(t *testing.T) {
  function TestArrayLiterals (line 435) | func TestArrayLiterals(t *testing.T) {
  function TestArrayIndexExpressions (line 453) | func TestArrayIndexExpressions(t *testing.T) {
  function TestDictLiterals (line 499) | func TestDictLiterals(t *testing.T) {
  function TestDictIndexExpression (line 539) | func TestDictIndexExpression(t *testing.T) {
  function TestPrefixInteger (line 585) | func TestPrefixInteger(t *testing.T) {
  function TestPrefixFloat (line 610) | func TestPrefixFloat(t *testing.T) {
  function TestInExpression (line 635) | func TestInExpression(t *testing.T) {
  function TestArrayConcatenation (line 676) | func TestArrayConcatenation(t *testing.T) {
  function TestDictConcatenation (line 708) | func TestDictConcatenation(t *testing.T) {
  function TestPostfixExpression (line 736) | func TestPostfixExpression(t *testing.T) {
  function TestWhileLoop (line 783) | func TestWhileLoop(t *testing.T) {
  function TestForLoop (line 803) | func TestForLoop(t *testing.T) {
  function TestBreakLoop (line 822) | func TestBreakLoop(t *testing.T) {
  function TestContinueLoop (line 865) | func TestContinueLoop(t *testing.T) {
  function TestSwitchStatement (line 909) | func TestSwitchStatement(t *testing.T) {
  function TestAssignEqual (line 987) | func TestAssignEqual(t *testing.T) {
  function TestStringMethods (line 1061) | func TestStringMethods(t *testing.T) {
  function TestTimeModule (line 1114) | func TestTimeModule(t *testing.T) {

FILE: evaluator/forin.go
  function evalForInExpression (line 8) | func evalForInExpression(fie *ast.ForIn, env *object.Environment, line i...

FILE: evaluator/function.go
  function evalFunction (line 8) | func evalFunction(node *ast.FunctionLiteral, env *object.Environment) ob...

FILE: evaluator/identifier.go
  function evalIdentifier (line 8) | func evalIdentifier(node *ast.Identifier, env *object.Environment) objec...

FILE: evaluator/if.go
  function evalIfExpression (line 8) | func evalIfExpression(ie *ast.IfExpression, env *object.Environment) obj...

FILE: evaluator/import.go
  function evalImport (line 18) | func evalImport(node *ast.Import, env *object.Environment) object.Object {
  function evalImportFile (line 29) | func evalImportFile(name string, ident *ast.Identifier, env *object.Envi...
  function addSearchPath (line 43) | func addSearchPath(path string) {
  function findFile (line 47) | func findFile(name string) string {
  function fileExists (line 58) | func fileExists(file string) bool {
  function evaluateFile (line 63) | func evaluateFile(file string, env *object.Environment) (*object.Environ...
  function importFile (line 83) | func importFile(name string, ident *ast.Identifier, env *object.Environm...

FILE: evaluator/in.go
  function evalInExpression (line 9) | func evalInExpression(left, right object.Object, line int) object.Object {
  function evalInStringExpression (line 22) | func evalInStringExpression(left, right object.Object) object.Object {
  function evalInDictExpression (line 32) | func evalInDictExpression(left, right object.Object, line int) object.Ob...
  function evalInArrayExpression (line 43) | func evalInArrayExpression(left, right object.Object) object.Object {

FILE: evaluator/index.go
  function evalIndexExpression (line 5) | func evalIndexExpression(left, index object.Object, line int) object.Obj...
  function evalArrayIndexExpression (line 18) | func evalArrayIndexExpression(array, index object.Object) object.Object {
  function evalDictIndexExpression (line 30) | func evalDictIndexExpression(dict, index object.Object, line int) object...

FILE: evaluator/infix.go
  function evalInfixExpression (line 10) | func evalInfixExpression(operator string, left, right object.Object, lin...
  function evalFloatIntegerInfixExpression (line 101) | func evalFloatIntegerInfixExpression(operator string, left, right object...
  function evalStringInfixExpression (line 149) | func evalStringInfixExpression(operator string, left, right object.Objec...
  function evalBooleanInfixExpression (line 166) | func evalBooleanInfixExpression(operator string, left, right object.Obje...
  function evalFloatInfixExpression (line 180) | func evalFloatInfixExpression(operator string, left, right object.Object...
  function evalIntegerInfixExpression (line 213) | func evalIntegerInfixExpression(operator string, left, right object.Obje...

FILE: evaluator/method.go
  function evalMethodExpression (line 8) | func evalMethodExpression(node *ast.MethodExpression, env *object.Enviro...
  function applyMethod (line 26) | func applyMethod(obj object.Object, method ast.Expression, args []object...
  function maap (line 68) | func maap(a *object.Array, args []object.Object) object.Object {
  function filter (line 90) | func filter(a *object.Array, args []object.Object) object.Object {

FILE: evaluator/package.go
  function evalPackage (line 8) | func evalPackage(node *ast.Package, env *object.Environment) object.Obje...

FILE: evaluator/postfix.go
  function evalPostfixExpression (line 8) | func evalPostfixExpression(env *object.Environment, operator string, nod...

FILE: evaluator/prefix.go
  function evalMinusPrefixOperatorExpression (line 5) | func evalMinusPrefixOperatorExpression(right object.Object, line int) ob...
  function evalPlusPrefixOperatorExpression (line 18) | func evalPlusPrefixOperatorExpression(right object.Object, line int) obj...
  function evalPrefixExpression (line 32) | func evalPrefixExpression(operator string, right object.Object, line int...

FILE: evaluator/property.go
  function evalPropertyExpression (line 8) | func evalPropertyExpression(node *ast.PropertyExpression, env *object.En...
  function evalPropertyAssignment (line 36) | func evalPropertyAssignment(name *ast.PropertyExpression, val object.Obj...

FILE: evaluator/switch.go
  function evalSwitchStatement (line 8) | func evalSwitchStatement(se *ast.SwitchExpression, env *object.Environme...

FILE: evaluator/type.go
  function convertToInteger (line 9) | func convertToInteger(obj object.Object) object.Object {
  function convertToFloat (line 31) | func convertToFloat(obj object.Object) object.Object {
  function convertToString (line 53) | func convertToString(obj object.Object) object.Object {
  function convertToBoolean (line 57) | func convertToBoolean(obj object.Object) object.Object {

FILE: evaluator/while.go
  constant MAX_ITERATIONS (line 8) | MAX_ITERATIONS = 1_000_000
  function evalWhileExpression (line 10) | func evalWhileExpression(we *ast.WhileExpression, env *object.Environmen...

FILE: lexer/lexer.go
  type Lexer (line 9) | type Lexer struct
    method readChar (line 23) | func (l *Lexer) readChar() {
    method NextToken (line 34) | func (l *Lexer) NextToken() token.Token {
    method readIdentifier (line 207) | func (l *Lexer) readIdentifier() string {
    method skipWhitespace (line 220) | func (l *Lexer) skipWhitespace() {
    method readNumber (line 233) | func (l *Lexer) readNumber() string {
    method readDecimal (line 241) | func (l *Lexer) readDecimal() token.Token {
    method peekChar (line 251) | func (l *Lexer) peekChar() rune {
    method skipSingleLineComment (line 267) | func (l *Lexer) skipSingleLineComment() {
    method skipMultiLineComment (line 274) | func (l *Lexer) skipMultiLineComment() {
    method readString (line 293) | func (l *Lexer) readString() string {
    method readSingleQuoteString (line 323) | func (l *Lexer) readSingleQuoteString() string {
  function New (line 17) | func New(input string) *Lexer {
  function newToken (line 203) | func newToken(tokenType token.TokenType, line int, ch rune) token.Token {
  function isLetter (line 216) | func isLetter(ch rune) bool {
  function isDigit (line 229) | func isDigit(ch rune) bool {

FILE: lexer/lexer_test.go
  function TestNextToken (line 9) | func TestNextToken(t *testing.T) {

FILE: main.go
  function main (line 35) | func main() {

FILE: main_wasm.go
  function Read (line 16) | func Read(contents string) {
  function runCode (line 45) | func runCode(this js.Value, args []js.Value) interface{} {
  function main (line 51) | func main() {

FILE: module/hisabati.go
  function pi (line 73) | func pi(args []object.Object, defs map[string]object.Object) object.Obje...
  function e (line 77) | func e(args []object.Object, defs map[string]object.Object) object.Object {
  function phi (line 81) | func phi(args []object.Object, defs map[string]object.Object) object.Obj...
  function ln10 (line 85) | func ln10(args []object.Object, defs map[string]object.Object) object.Ob...
  function ln2 (line 89) | func ln2(args []object.Object, defs map[string]object.Object) object.Obj...
  function log10e (line 93) | func log10e(args []object.Object, defs map[string]object.Object) object....
  function log2e (line 97) | func log2e(args []object.Object, defs map[string]object.Object) object.O...
  function sqrt1_2 (line 101) | func sqrt1_2(args []object.Object, defs map[string]object.Object) object...
  function sqrt2 (line 105) | func sqrt2(args []object.Object, defs map[string]object.Object) object.O...
  function sqrt3 (line 109) | func sqrt3(args []object.Object, defs map[string]object.Object) object.O...
  function sqrt5 (line 113) | func sqrt5(args []object.Object, defs map[string]object.Object) object.O...
  function epsilon (line 117) | func epsilon(args []object.Object, defs map[string]object.Object) object...
  function abs (line 121) | func abs(args []object.Object, defs map[string]object.Object) object.Obj...
  function sign (line 147) | func sign(args []object.Object, defs map[string]object.Object) object.Ob...
  function ceil (line 176) | func ceil(args []object.Object, defs map[string]object.Object) object.Ob...
  function floor (line 196) | func floor(args []object.Object, defs map[string]object.Object) object.O...
  function sqrt (line 216) | func sqrt(args []object.Object, defs map[string]object.Object) object.Ob...
  function cbrt (line 236) | func cbrt(args []object.Object, defs map[string]object.Object) object.Ob...
  function root (line 256) | func root(args []object.Object, defs map[string]object.Object) object.Ob...
  function hypot (line 289) | func hypot(args []object.Object, defs map[string]object.Object) object.O...
  function factorial (line 311) | func factorial(args []object.Object, defs map[string]object.Object) obje...
  function round (line 332) | func round(args []object.Object, defs map[string]object.Object) object.O...
  function max (line 347) | func max(args []object.Object, defs map[string]object.Object) object.Obj...
  function min (line 388) | func min(args []object.Object, defs map[string]object.Object) object.Obj...
  function exp (line 429) | func exp(args []object.Object, defs map[string]object.Object) object.Obj...
  function expm1 (line 443) | func expm1(args []object.Object, defs map[string]object.Object) object.O...
  function log (line 457) | func log(args []object.Object, defs map[string]object.Object) object.Obj...
  function log10 (line 471) | func log10(args []object.Object, defs map[string]object.Object) object.O...
  function log2 (line 485) | func log2(args []object.Object, defs map[string]object.Object) object.Ob...
  function extractFloatValue (line 505) | func extractFloatValue(obj object.Object) float64 {
  function log1p (line 516) | func log1p(args []object.Object, defs map[string]object.Object) object.O...
  function cos (line 530) | func cos(args []object.Object, defs map[string]object.Object) object.Obj...
  function sin (line 544) | func sin(args []object.Object, defs map[string]object.Object) object.Obj...
  function tan (line 558) | func tan(args []object.Object, defs map[string]object.Object) object.Obj...
  function acos (line 572) | func acos(args []object.Object, defs map[string]object.Object) object.Ob...
  function asin (line 586) | func asin(args []object.Object, defs map[string]object.Object) object.Ob...
  function atan (line 600) | func atan(args []object.Object, defs map[string]object.Object) object.Ob...
  function cosh (line 614) | func cosh(args []object.Object, defs map[string]object.Object) object.Ob...
  function sinh (line 628) | func sinh(args []object.Object, defs map[string]object.Object) object.Ob...
  function tanh (line 642) | func tanh(args []object.Object, defs map[string]object.Object) object.Ob...
  function acosh (line 656) | func acosh(args []object.Object, defs map[string]object.Object) object.O...
  function asinh (line 670) | func asinh(args []object.Object, defs map[string]object.Object) object.O...
  function atan2 (line 684) | func atan2(args []object.Object, defs map[string]object.Object) object.O...
  function atanh (line 704) | func atanh(args []object.Object, defs map[string]object.Object) object.O...
  function random (line 718) | func random(args []object.Object, defs map[string]object.Object) object....

FILE: module/json.go
  function init (line 11) | func init() {
  function decode (line 16) | func decode(args []object.Object, defs map[string]object.Object) object....
  function convertWhateverToObject (line 39) | func convertWhateverToObject(i interface{}) object.Object {
  function encode (line 77) | func encode(args []object.Object, defs map[string]object.Object) object....
  function convertObjectToWhatever (line 93) | func convertObjectToWhatever(obj object.Object) interface{} {

FILE: module/module.go
  function init (line 7) | func init() {

FILE: module/net.go
  function init (line 14) | func init() {
  function getRequest (line 19) | func getRequest(args []object.Object, defs map[string]object.Object) obj...
  function postRequest (line 126) | func postRequest(args []object.Object, defs map[string]object.Object) ob...

FILE: module/os.go
  function init (line 13) | func init() {
  function exit (line 18) | func exit(args []object.Object, defs map[string]object.Object) object.Ob...
  function run (line 37) | func run(args []object.Object, defs map[string]object.Object) object.Obj...

FILE: module/time.go
  function init (line 13) | func init() {
  function now (line 23) | func now(args []object.Object, defs map[string]object.Object) object.Obj...
  function sleep (line 34) | func sleep(args []object.Object, defs map[string]object.Object) object.O...
  function since (line 54) | func since(args []object.Object, defs map[string]object.Object) object.O...
  function today (line 88) | func today(args []object.Object, defs map[string]object.Object) object.O...
  function after (line 97) | func after(args []object.Object, defs map[string]object.Object) object.O...
  function diff (line 112) | func diff(args []object.Object, defs map[string]object.Object) object.Ob...
  function addTime (line 140) | func addTime(args []object.Object, defs map[string]object.Object) object...
  function getInt (line 177) | func getInt(obj object.Object) int {

FILE: object/array.go
  type Array (line 8) | type Array struct
    method Type (line 13) | func (ao *Array) Type() ObjectType { return ARRAY_OBJ }
    method Inspect (line 14) | func (ao *Array) Inspect() string {
    method Next (line 33) | func (ao *Array) Next() (Object, Object) {
    method Reset (line 42) | func (ao *Array) Reset() {
    method Method (line 46) | func (a *Array) Method(method string, args []Object) Object {
    method len (line 65) | func (a *Array) len(args []Object) Object {
    method last (line 72) | func (a *Array) last() Object {
    method push (line 80) | func (a *Array) push(args []Object) Object {
    method join (line 85) | func (a *Array) join(args []Object) Object {
    method filter (line 105) | func (a *Array) filter(args []Object) Object {
    method find (line 120) | func (a *Array) find(args []Object) Object {

FILE: object/at.go
  type At (line 5) | type At struct
    method Type (line 9) | func (a *At) Type() ObjectType { return AT }
    method Inspect (line 10) | func (a *At) Inspect() string {

FILE: object/bool.go
  type Boolean (line 3) | type Boolean struct
    method Inspect (line 7) | func (b *Boolean) Inspect() string {
    method Type (line 14) | func (b *Boolean) Type() ObjectType { return BOOLEAN_OBJ }
    method HashKey (line 16) | func (b *Boolean) HashKey() HashKey {

FILE: object/break.go
  type Break (line 3) | type Break struct
    method Type (line 5) | func (b *Break) Type() ObjectType { return BREAK_OBJ }
    method Inspect (line 6) | func (b *Break) Inspect() string  { return "break" }

FILE: object/builtin.go
  type BuiltinFunction (line 3) | type BuiltinFunction
  type Builtin (line 5) | type Builtin struct
    method Inspect (line 9) | func (b *Builtin) Inspect() string  { return "builtin function" }
    method Type (line 10) | func (b *Builtin) Type() ObjectType { return BUILTIN_OBJ }

FILE: object/byte.go
  type Byte (line 3) | type Byte struct
    method Inspect (line 8) | func (b *Byte) Inspect() string  { return "b" + b.String }
    method Type (line 9) | func (b *Byte) Type() ObjectType { return BYTE_OBJ }

FILE: object/continue.go
  type Continue (line 3) | type Continue struct
    method Type (line 5) | func (c *Continue) Type() ObjectType { return CONTINUE_OBJ }
    method Inspect (line 6) | func (c *Continue) Inspect() string  { return "continue" }

FILE: object/dict.go
  type DictPair (line 10) | type DictPair struct
  type Dict (line 15) | type Dict struct
    method Type (line 20) | func (d *Dict) Type() ObjectType { return DICT_OBJ }
    method Inspect (line 21) | func (d *Dict) Inspect() string {
    method Next (line 37) | func (d *Dict) Next() (Object, Object) {
    method Reset (line 58) | func (d *Dict) Reset() {

FILE: object/environment.go
  function NewEnclosedEnvironment (line 3) | func NewEnclosedEnvironment(outer *Environment) *Environment {
  function NewEnvironment (line 9) | func NewEnvironment() *Environment {
  type Environment (line 14) | type Environment struct
    method Get (line 19) | func (e *Environment) Get(name string) (Object, bool) {
    method Set (line 28) | func (e *Environment) Set(name string, val Object) Object {
    method Del (line 33) | func (e *Environment) Del(name string) bool {

FILE: object/error.go
  type Error (line 6) | type Error struct
    method Inspect (line 10) | func (e *Error) Inspect() string {
    method Type (line 14) | func (e *Error) Type() ObjectType { return ERROR_OBJ }

FILE: object/error_wasm.go
  type Error (line 4) | type Error struct
    method Inspect (line 8) | func (e *Error) Inspect() string {
    method Type (line 12) | func (e *Error) Type() ObjectType { return ERROR_OBJ }

FILE: object/file.go
  type File (line 7) | type File struct
    method Type (line 12) | func (f *File) Type() ObjectType { return FILE_OBJ }
    method Inspect (line 13) | func (f *File) Inspect() string  { return f.Filename }
    method Method (line 14) | func (f *File) Method(method string, args []Object) Object {
    method read (line 26) | func (f *File) read(args []Object) Object {
    method write (line 33) | func (f *File) write(args []Object) Object {
    method append (line 49) | func (f *File) append(args []Object) Object {

FILE: object/float.go
  type Float (line 8) | type Float struct
    method Inspect (line 12) | func (f *Float) Inspect() string  { return strconv.FormatFloat(f.Value...
    method Type (line 13) | func (f *Float) Type() ObjectType { return FLOAT_OBJ }
    method HashKey (line 15) | func (f *Float) HashKey() HashKey {

FILE: object/function.go
  type Function (line 10) | type Function struct
    method Type (line 18) | func (f *Function) Type() ObjectType { return FUNCTION_OBJ }
    method Inspect (line 19) | func (f *Function) Inspect() string {

FILE: object/instance.go
  type Instance (line 5) | type Instance struct
    method Type (line 10) | func (i *Instance) Type() ObjectType { return INSTANCE }
    method Inspect (line 11) | func (i *Instance) Inspect() string {

FILE: object/integer.go
  type Integer (line 5) | type Integer struct
    method Inspect (line 9) | func (i *Integer) Inspect() string  { return fmt.Sprintf("%d", i.Value) }
    method Type (line 10) | func (i *Integer) Type() ObjectType { return INTEGER_OBJ }
    method HashKey (line 12) | func (i *Integer) HashKey() HashKey {

FILE: object/module.go
  type ModuleFunction (line 3) | type ModuleFunction
  type Module (line 5) | type Module struct
    method Type (line 10) | func (m *Module) Type() ObjectType {
    method Inspect (line 20) | func (m *Module) Inspect() string { return "Module: " + m.Name }

FILE: object/null.go
  type Null (line 3) | type Null struct
    method Inspect (line 5) | func (n *Null) Inspect() string  { return "null" }
    method Type (line 6) | func (n *Null) Type() ObjectType { return NULL_OBJ }

FILE: object/object.go
  type ObjectType (line 7) | type ObjectType
  constant INTEGER_OBJ (line 10) | INTEGER_OBJ      = "NAMBA"
  constant FLOAT_OBJ (line 11) | FLOAT_OBJ        = "DESIMALI"
  constant BOOLEAN_OBJ (line 12) | BOOLEAN_OBJ      = "BOOLEAN"
  constant NULL_OBJ (line 13) | NULL_OBJ         = "TUPU"
  constant RETURN_VALUE_OBJ (line 14) | RETURN_VALUE_OBJ = "RUDISHA"
  constant ERROR_OBJ (line 15) | ERROR_OBJ        = "KOSA"
  constant FUNCTION_OBJ (line 16) | FUNCTION_OBJ     = "UNDO (FUNCTION)"
  constant STRING_OBJ (line 17) | STRING_OBJ       = "NENO"
  constant BUILTIN_OBJ (line 18) | BUILTIN_OBJ      = "YA_NDANI"
  constant ARRAY_OBJ (line 19) | ARRAY_OBJ        = "ORODHA"
  constant DICT_OBJ (line 20) | DICT_OBJ         = "KAMUSI"
  constant CONTINUE_OBJ (line 21) | CONTINUE_OBJ     = "ENDELEA"
  constant BREAK_OBJ (line 22) | BREAK_OBJ        = "VUNJA"
  constant FILE_OBJ (line 23) | FILE_OBJ         = "FAILI"
  constant TIME_OBJ (line 24) | TIME_OBJ         = "MUDA"
  constant JSON_OBJ (line 25) | JSON_OBJ         = "JSONI"
  constant MODULE_OBJ (line 26) | MODULE_OBJ       = "MODULE"
  constant BYTE_OBJ (line 27) | BYTE_OBJ         = "BYTE"
  constant PACKAGE_OBJ (line 28) | PACKAGE_OBJ      = "PAKEJI"
  constant INSTANCE (line 29) | INSTANCE         = "PAKEJI"
  constant AT (line 30) | AT               = "@"
  type Object (line 33) | type Object interface
  type HashKey (line 38) | type HashKey struct
  type Hashable (line 43) | type Hashable interface
  type Iterable (line 48) | type Iterable interface
  function newError (line 53) | func newError(format string, a ...interface{}) *Error {

FILE: object/object_test.go
  function TestStringHashKey (line 5) | func TestStringHashKey(t *testing.T) {

FILE: object/package.go
  type Package (line 9) | type Package struct
    method Type (line 15) | func (p *Package) Type() ObjectType { return PACKAGE_OBJ }
    method Inspect (line 16) | func (p *Package) Inspect() string {

FILE: object/return.go
  type ReturnValue (line 3) | type ReturnValue struct
    method Inspect (line 7) | func (rv *ReturnValue) Inspect() string  { return rv.Value.Inspect() }
    method Type (line 8) | func (rv *ReturnValue) Type() ObjectType { return RETURN_VALUE_OBJ }

FILE: object/strings.go
  type String (line 10) | type String struct
    method Inspect (line 15) | func (s *String) Inspect() string  { return s.Value }
    method Type (line 16) | func (s *String) Type() ObjectType { return STRING_OBJ }
    method HashKey (line 17) | func (s *String) HashKey() HashKey {
    method Next (line 23) | func (s *String) Next() (Object, Object) {
    method Reset (line 31) | func (s *String) Reset() {
    method Method (line 34) | func (s *String) Method(method string, args []Object) Object {
    method len (line 51) | func (s *String) len(args []Object) Object {
    method upper (line 58) | func (s *String) upper(args []Object) Object {
    method lower (line 65) | func (s *String) lower(args []Object) Object {
    method split (line 72) | func (s *String) split(args []Object) Object {
    method format (line 89) | func (s *String) format(args []Object) Object {
  function formatStr (line 99) | func formatStr(format string, options []Object) (string, error) {

FILE: object/time.go
  type Time (line 9) | type Time struct
    method Type (line 13) | func (t *Time) Type() ObjectType { return TIME_OBJ }
    method Inspect (line 14) | func (t *Time) Inspect() string  { return t.TimeValue }
    method Method (line 15) | func (t *Time) Method(method string, args []Object, defs map[string]Ob...
    method add (line 25) | func (t *Time) add(args []Object, defs map[string]Object) Object {
    method since (line 77) | func (t *Time) since(args []Object, defs map[string]Object) Object {

FILE: parser/arrays.go
  method parseArrayLiteral (line 8) | func (p *Parser) parseArrayLiteral() ast.Expression {
  method parseExpressionList (line 16) | func (p *Parser) parseExpressionList(end token.TokenType) []ast.Expressi...

FILE: parser/assignEqual.go
  method parseAssignEqualExpression (line 9) | func (p *Parser) parseAssignEqualExpression(exp ast.Expression) ast.Expr...

FILE: parser/assignment.go
  method parseAssignmentExpression (line 9) | func (p *Parser) parseAssignmentExpression(exp ast.Expression) ast.Expre...

FILE: parser/at.go
  method parseAt (line 5) | func (p *Parser) parseAt() ast.Expression {

FILE: parser/boolean.go
  method parseBoolean (line 8) | func (p *Parser) parseBoolean() ast.Expression {

FILE: parser/break.go
  method parseBreak (line 8) | func (p *Parser) parseBreak() *ast.Break {

FILE: parser/continue.go
  method parseContinue (line 8) | func (p *Parser) parseContinue() *ast.Continue {

FILE: parser/dict.go
  method parseDictLiteral (line 8) | func (p *Parser) parseDictLiteral() ast.Expression {

FILE: parser/dot.go
  method parseMethod (line 8) | func (p *Parser) parseMethod(obj ast.Expression) ast.Expression {

FILE: parser/float.go
  method parseFloatLiteral (line 10) | func (p *Parser) parseFloatLiteral() ast.Expression {

FILE: parser/for.go
  method parseForExpression (line 8) | func (p *Parser) parseForExpression() ast.Expression {
  method parseForInExpression (line 63) | func (p *Parser) parseForInExpression(initialExpression *ast.For) ast.Ex...

FILE: parser/function.go
  method parseFunctionLiteral (line 8) | func (p *Parser) parseFunctionLiteral() ast.Expression {
  method parseFunctionParameters (line 33) | func (p *Parser) parseFunctionParameters(lit *ast.FunctionLiteral) bool {
  method parseCallExpression (line 63) | func (p *Parser) parseCallExpression(function ast.Expression) ast.Expres...

FILE: parser/identifier.go
  method parseIdentifier (line 7) | func (p *Parser) parseIdentifier() ast.Expression {

FILE: parser/if.go
  method parseIfExpression (line 8) | func (p *Parser) parseIfExpression() ast.Expression {

FILE: parser/import.go
  method parseImport (line 8) | func (p *Parser) parseImport() ast.Expression {

FILE: parser/index.go
  method parseIndexExpression (line 8) | func (p *Parser) parseIndexExpression(left ast.Expression) ast.Expression {

FILE: parser/integer.go
  method parseIntegerLiteral (line 10) | func (p *Parser) parseIntegerLiteral() ast.Expression {

FILE: parser/null.go
  method parseNull (line 7) | func (p *Parser) parseNull() ast.Expression {

FILE: parser/package.go
  method parsePackage (line 8) | func (p *Parser) parsePackage() ast.Expression {

FILE: parser/parser.go
  constant _ (line 12) | _ int = iota
  constant LOWEST (line 13) | LOWEST
  constant ASSIGN (line 14) | ASSIGN
  constant COND (line 15) | COND
  constant EQUALS (line 16) | EQUALS
  constant LESSGREATER (line 17) | LESSGREATER
  constant SUM (line 18) | SUM
  constant PRODUCT (line 19) | PRODUCT
  constant POWER (line 20) | POWER
  constant MODULUS (line 21) | MODULUS
  constant PREFIX (line 22) | PREFIX
  constant CALL (line 23) | CALL
  constant INDEX (line 24) | INDEX
  constant DOT (line 25) | DOT
  type prefixParseFn (line 57) | type prefixParseFn
  type infixParseFn (line 58) | type infixParseFn
  type postfixParseFn (line 59) | type postfixParseFn
  type Parser (line 62) | type Parser struct
    method registerPrefix (line 76) | func (p *Parser) registerPrefix(tokenType token.TokenType, fn prefixPa...
    method registerInfix (line 80) | func (p *Parser) registerInfix(tokenType token.TokenType, fn infixPars...
    method registerPostfix (line 84) | func (p *Parser) registerPostfix(tokenType token.TokenType, fn postfix...
    method ParseProgram (line 150) | func (p *Parser) ParseProgram() *ast.Program {
    method nextToken (line 165) | func (p *Parser) nextToken() {
    method curTokenIs (line 171) | func (p *Parser) curTokenIs(t token.TokenType) bool {
    method peekTokenIs (line 175) | func (p *Parser) peekTokenIs(t token.TokenType) bool {
    method expectPeek (line 179) | func (p *Parser) expectPeek(t token.TokenType) bool {
    method peekPrecedence (line 189) | func (p *Parser) peekPrecedence() int {
    method curPrecedence (line 196) | func (p *Parser) curPrecedence() int {
    method Errors (line 206) | func (p *Parser) Errors() []string {
    method peekError (line 210) | func (p *Parser) peekError(t token.TokenType) {
    method parseExpressionStatement (line 217) | func (p *Parser) parseExpressionStatement() *ast.ExpressionStatement {
    method parseExpression (line 229) | func (p *Parser) parseExpression(precedence int) ast.Expression {
    method parsePrefixExpression (line 257) | func (p *Parser) parsePrefixExpression() ast.Expression {
    method noPrefixParseFnError (line 270) | func (p *Parser) noPrefixParseFnError(t token.TokenType) {
    method parseInfixExpression (line 277) | func (p *Parser) parseInfixExpression(left ast.Expression) ast.Express...
    method noInfixParseFnError (line 290) | func (p *Parser) noInfixParseFnError(t token.TokenType) {
    method parseGroupedExpression (line 295) | func (p *Parser) parseGroupedExpression() ast.Expression {
    method parsePostfixExpression (line 309) | func (p *Parser) parsePostfixExpression() ast.Expression {
  function New (line 88) | func New(l *lexer.Lexer) *Parser {

FILE: parser/parser_test.go
  function TestLetStatements (line 11) | func TestLetStatements(t *testing.T) {
  function testLetStatement (line 45) | func testLetStatement(t *testing.T, s ast.Statement, name string) bool {
  function checkParserErrors (line 69) | func checkParserErrors(t *testing.T, p *Parser) {
  function TestReturnStatements (line 84) | func TestReturnStatements(t *testing.T) {
  function TestIdentifierExpression (line 120) | func TestIdentifierExpression(t *testing.T) {
  function TestIntergerLiteral (line 152) | func TestIntergerLiteral(t *testing.T) {
  function TestParsingPrefixExpressions (line 183) | func TestParsingPrefixExpressions(t *testing.T) {
  function testIntegerLiteral (line 225) | func testIntegerLiteral(t *testing.T, il ast.Expression, value int64) bo...
  function TestParsingInfixExpressions (line 245) | func TestParsingInfixExpressions(t *testing.T) {
  function TestOperatorPrecedenceParsing (line 290) | func TestOperatorPrecedenceParsing(t *testing.T) {
  function testIdentifier (line 415) | func testIdentifier(t *testing.T, exp ast.Expression, value string) bool {
  function testLiteralExpression (line 435) | func testLiteralExpression(
  function testBooleanLiteral (line 455) | func testBooleanLiteral(t *testing.T, exp ast.Expression, value bool) bo...
  function testInfixExpression (line 470) | func testInfixExpression(
  function TestBooleanExpression (line 499) | func TestBooleanExpression(t *testing.T) {
  function TestIfExpression (line 536) | func TestIfExpression(t *testing.T) {
  function TestIfElseExpression (line 580) | func TestIfElseExpression(t *testing.T) {
  function TestFunctionLiteralParsing (line 639) | func TestFunctionLiteralParsing(t *testing.T) {
  function TestFunctionParameterParsing (line 680) | func TestFunctionParameterParsing(t *testing.T) {
  function TestCallExpressionParsing (line 709) | func TestCallExpressionParsing(t *testing.T) {
  function TestStringLiteralExpression (line 745) | func TestStringLiteralExpression(t *testing.T) {
  function TestParsingArrayLiterals (line 764) | func TestParsingArrayLiterals(t *testing.T) {
  function TestParsingIndexExpressions (line 783) | func TestParsingIndexExpressions(t *testing.T) {
  function TestParsingDictLiteralsStringKeys (line 806) | func TestParsingDictLiteralsStringKeys(t *testing.T) {
  function TestParsingDictLiteralsIntegerKeys (line 841) | func TestParsingDictLiteralsIntegerKeys(t *testing.T) {
  function TestParsingDictLiteralsBoolKeys (line 876) | func TestParsingDictLiteralsBoolKeys(t *testing.T) {
  function TestParsingDictLiteralWithExpressions (line 910) | func TestParsingDictLiteralWithExpressions(t *testing.T) {
  function TestParsingEmptyDict (line 957) | func TestParsingEmptyDict(t *testing.T) {
  function TestWhileLoop (line 976) | func TestWhileLoop(t *testing.T) {
  function TestShorthandAssignment (line 1017) | func TestShorthandAssignment(t *testing.T) {
  function TestForExpression (line 1035) | func TestForExpression(t *testing.T) {
  function TestParsePostfix (line 1067) | func TestParsePostfix(t *testing.T) {
  function TestParseDot (line 1081) | func TestParseDot(t *testing.T) {
  function TestParseSwitch (line 1095) | func TestParseSwitch(t *testing.T) {
  function TestParseImport (line 1116) | func TestParseImport(t *testing.T) {

FILE: parser/statements.go
  method parseStatement (line 10) | func (p *Parser) parseStatement() ast.Statement {
  method parseLetStatement (line 25) | func (p *Parser) parseLetStatement() *ast.LetStatement {
  method parseReturnStatement (line 49) | func (p *Parser) parseReturnStatement() *ast.ReturnStatement {
  method parseBlockStatement (line 62) | func (p *Parser) parseBlockStatement() *ast.BlockStatement {

FILE: parser/string.go
  method parseStringLiteral (line 7) | func (p *Parser) parseStringLiteral() ast.Expression {

FILE: parser/switch.go
  method parseSwitchStatement (line 10) | func (p *Parser) parseSwitchStatement() ast.Expression {

FILE: parser/while.go
  method parseWhileExpression (line 8) | func (p *Parser) parseWhileExpression() ast.Expression {

FILE: repl/docs.go
  type item (line 40) | type item struct
    method Title (line 44) | func (i item) Title() string       { return i.title }
    method Description (line 45) | func (i item) Description() string { return i.desc }
    method FilterValue (line 46) | func (i item) FilterValue() string { return i.title }
  type languages (line 48) | type languages struct
    method Title (line 52) | func (l languages) Title() string       { return l.title }
    method Description (line 53) | func (l languages) Description() string { return l.desc }
    method FilterValue (line 54) | func (l languages) FilterValue() string { return l.title }
  type playground (line 56) | type playground struct
    method Init (line 75) | func (pg playground) Init() tea.Cmd {
    method Update (line 79) | func (pg playground) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
    method View (line 319) | func (pg playground) View() string {

FILE: repl/repl.go
  constant PROMPT (line 22) | PROMPT = ">>> "
  function Read (line 27) | func Read(contents string) {
  function Start (line 52) | func Start() {
  type dummy (line 67) | type dummy struct
    method executor (line 71) | func (d *dummy) executor(in string) {
  function completer (line 96) | func completer(in prompt.Document) []prompt.Suggest {
  function Docs (line 100) | func Docs() {

FILE: token/token.go
  type TokenType (line 5) | type TokenType
  type Token (line 7) | type Token struct
  constant ILLEGAL (line 14) | ILLEGAL = "HARAMU"
  constant EOF (line 15) | EOF     = "MWISHO"
  constant IDENT (line 18) | IDENT  = "KITAMBULISHI"
  constant INT (line 19) | INT    = "NAMBA"
  constant STRING (line 20) | STRING = "NENO"
  constant FLOAT (line 21) | FLOAT  = "DESIMALI"
  constant ASSIGN (line 24) | ASSIGN          = "="
  constant PLUS (line 25) | PLUS            = "+"
  constant MINUS (line 26) | MINUS           = "-"
  constant BANG (line 27) | BANG            = "!"
  constant ASTERISK (line 28) | ASTERISK        = "*"
  constant POW (line 29) | POW             = "**"
  constant SLASH (line 30) | SLASH           = "/"
  constant MODULUS (line 31) | MODULUS         = "%"
  constant LT (line 32) | LT              = "<"
  constant LTE (line 33) | LTE             = "<="
  constant GT (line 34) | GT              = ">"
  constant GTE (line 35) | GTE             = ">="
  constant EQ (line 36) | EQ              = "=="
  constant NOT_EQ (line 37) | NOT_EQ          = "!="
  constant AND (line 38) | AND             = "&&"
  constant OR (line 39) | OR              = "||"
  constant PLUS_ASSIGN (line 40) | PLUS_ASSIGN     = "+="
  constant PLUS_PLUS (line 41) | PLUS_PLUS       = "++"
  constant MINUS_ASSIGN (line 42) | MINUS_ASSIGN    = "-="
  constant MINUS_MINUS (line 43) | MINUS_MINUS     = "--"
  constant ASTERISK_ASSIGN (line 44) | ASTERISK_ASSIGN = "*="
  constant SLASH_ASSIGN (line 45) | SLASH_ASSIGN    = "/="
  constant MODULUS_ASSIGN (line 46) | MODULUS_ASSIGN  = "%="
  constant SHEBANG (line 47) | SHEBANG         = "#!"
  constant COMMA (line 50) | COMMA     = ","
  constant SEMICOLON (line 51) | SEMICOLON = ";"
  constant LPAREN (line 52) | LPAREN    = "("
  constant RPAREN (line 53) | RPAREN    = ")"
  constant LBRACE (line 54) | LBRACE    = "{"
  constant RBRACE (line 55) | RBRACE    = "}"
  constant LBRACKET (line 56) | LBRACKET  = "["
  constant RBRACKET (line 57) | RBRACKET  = "]"
  constant COLON (line 58) | COLON     = ":"
  constant DOT (line 59) | DOT       = "."
  constant AT (line 60) | AT        = "@"
  constant FUNCTION (line 63) | FUNCTION = "FUNCTION"
  constant LET (line 64) | LET      = "FANYA"
  constant TRUE (line 65) | TRUE     = "KWELI"
  constant FALSE (line 66) | FALSE    = "SIKWELI"
  constant IF (line 67) | IF       = "KAMA"
  constant ELSE (line 68) | ELSE     = "SIVYO"
  constant RETURN (line 69) | RETURN   = "RUDISHA"
  constant WHILE (line 70) | WHILE    = "WAKATI"
  constant NULL (line 71) | NULL     = "TUPU"
  constant BREAK (line 72) | BREAK    = "VUNJA"
  constant CONTINUE (line 73) | CONTINUE = "ENDELEA"
  constant IN (line 74) | IN       = "KTK"
  constant FOR (line 75) | FOR      = "KWA"
  constant SWITCH (line 76) | SWITCH   = "BADILI"
  constant CASE (line 77) | CASE     = "IKIWA"
  constant DEFAULT (line 78) | DEFAULT  = "KAWAIDA"
  constant IMPORT (line 79) | IMPORT   = "TUMIA"
  constant PACKAGE (line 80) | PACKAGE  = "PAKEJI"
  function LookupIdent (line 106) | func LookupIdent(ident string) TokenType {
Condensed preview — 166 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (452K chars).
[
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.yml",
    "chars": 2412,
    "preview": "name: 🐛 Bug Report\ndescription: Report a bug\ntitle: (bug report summary)\nlabels: Bug\nbody:\n  - type: textarea\n    id: de"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request.yml",
    "chars": 1801,
    "preview": "name: 🚀 Feature Request\ndescription: Suggest an idea for this project\ntitle: (feature request summary)\nlabels: Feature R"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE",
    "chars": 672,
    "preview": "\n\n<!--\n\nPlease title your PR as follows: `module: description` (e.g. `time: fix date format`).\nAlways start with the thi"
  },
  {
    "path": ".github/workflows/build.yml",
    "chars": 572,
    "preview": "name: Go\n\non:\n  push:\n    tags:\n      - \"*\"\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/ch"
  },
  {
    "path": ".github/workflows/tests.yml",
    "chars": 284,
    "preview": "name: Go\n\non:\n  push:\n    branches: [ main, dev ]\n\njobs:\n\n  build:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: act"
  },
  {
    "path": ".gitignore",
    "chars": 802,
    "preview": ".DS_Store\n*.[56789ao]\n*.a[56789o]\n*.so\n*.pyc\n._*\n.nfs.*\n[56789a].out\n*~\n*.orig\n*.rej\n*.exe\n.*.swp\ncore\n*.cgo*.go\n*.cgo*."
  },
  {
    "path": ".goreleaser.yaml",
    "chars": 944,
    "preview": "project_name: nuru\nbefore:\n  hooks:\n    - go mod tidy\n    - go generate ./...\n\nbuilds:\n  - env:\n      - CGO_ENABLED=0\n  "
  },
  {
    "path": "ABOUT.md",
    "chars": 4938,
    "preview": "# NURU PROGRAMMING LANGUAGE\n\nThis page intends to show the origins of Nuru, its purpose, what it can be used for, what i"
  },
  {
    "path": "LICENSE",
    "chars": 18092,
    "preview": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Fr"
  },
  {
    "path": "Makefile",
    "chars": 1698,
    "preview": "VERSION=0.5.1\n\nbuild_linux:\n\t@echo 'building linux binary...'\n\tenv GOOS=linux GOARCH=amd64 go build -ldflags=\"-s -w\" -o "
  },
  {
    "path": "README.md",
    "chars": 9783,
    "preview": "<h1 align=\"center\">NURU🔥PROGRAMMING🔥LANGUAGE</h1>\n<p align=\"center\">\n    <a href=\"https://github.com/NuruProgramming/Nur"
  },
  {
    "path": "ast/ast.go",
    "chars": 14933,
    "preview": "package ast\n\nimport (\n\t\"bytes\"\n\t\"strings\"\n\n\t\"github.com/NuruProgramming/Nuru/token\"\n)\n\ntype Node interface {\n\tTokenLiter"
  },
  {
    "path": "ast/ast_test.go",
    "chars": 610,
    "preview": "package ast\n\nimport (\n\t\"testing\"\n\n\t\"github.com/NuruProgramming/Nuru/token\"\n)\n\nfunc TestString(t *testing.T) {\n\tprogram :"
  },
  {
    "path": "evaluator/assign.go",
    "chars": 305,
    "preview": "package evaluator\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nfunc eva"
  },
  {
    "path": "evaluator/assignEqual.go",
    "chars": 5405,
    "preview": "package evaluator\n\nimport (\n\t\"strings\"\n\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/object\""
  },
  {
    "path": "evaluator/at.go",
    "chars": 266,
    "preview": "package evaluator\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nfunc eva"
  },
  {
    "path": "evaluator/bang.go",
    "chars": 263,
    "preview": "package evaluator\n\nimport \"github.com/NuruProgramming/Nuru/object\"\n\nfunc evalBangOperatorExpression(right object.Object)"
  },
  {
    "path": "evaluator/block.go",
    "chars": 521,
    "preview": "package evaluator\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nfunc eva"
  },
  {
    "path": "evaluator/builtins.go",
    "chars": 1740,
    "preview": "//go:build !js || !wasm \n\npackage evaluator\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/NuruProgrammi"
  },
  {
    "path": "evaluator/builtins_common.go",
    "chars": 5059,
    "preview": "package evaluator\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nvar commonBuiltins = m"
  },
  {
    "path": "evaluator/builtins_wasm.go",
    "chars": 1772,
    "preview": "//go:build wasm && js\n\n// Modified version with of the builtins.go file with browser friendly versions of functions.\npac"
  },
  {
    "path": "evaluator/call.go",
    "chars": 2562,
    "preview": "package evaluator\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nfunc eva"
  },
  {
    "path": "evaluator/dict.go",
    "chars": 709,
    "preview": "package evaluator\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nfunc eva"
  },
  {
    "path": "evaluator/error_handler.go",
    "chars": 204,
    "preview": "package evaluator\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nfunc newError(format string, a ...inter"
  },
  {
    "path": "evaluator/evaluator.go",
    "chars": 9145,
    "preview": "package evaluator\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nvar (\n\tN"
  },
  {
    "path": "evaluator/evaluator_test.go",
    "chars": 21103,
    "preview": "package evaluator\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/NuruProgramming/Nuru/lexer\"\n\t\"github.com/NuruProgram"
  },
  {
    "path": "evaluator/forin.go",
    "chars": 756,
    "preview": "package evaluator\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nfunc eva"
  },
  {
    "path": "evaluator/function.go",
    "chars": 381,
    "preview": "package evaluator\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nfunc eva"
  },
  {
    "path": "evaluator/identifier.go",
    "chars": 403,
    "preview": "package evaluator\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nfunc eva"
  },
  {
    "path": "evaluator/if.go",
    "chars": 444,
    "preview": "package evaluator\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nfunc eva"
  },
  {
    "path": "evaluator/import.go",
    "chars": 2151,
    "preview": "package evaluator\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.co"
  },
  {
    "path": "evaluator/in.go",
    "chars": 1935,
    "preview": "package evaluator\n\nimport (\n\t\"strings\"\n\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nfunc evalInExpression(left, right o"
  },
  {
    "path": "evaluator/index.go",
    "chars": 1261,
    "preview": "package evaluator\n\nimport \"github.com/NuruProgramming/Nuru/object\"\n\nfunc evalIndexExpression(left, index object.Object, "
  },
  {
    "path": "evaluator/infix.go",
    "chars": 8146,
    "preview": "package evaluator\n\nimport (\n\t\"math\"\n\t\"strings\"\n\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nfunc evalInfixExpression(op"
  },
  {
    "path": "evaluator/method.go",
    "chars": 3231,
    "preview": "package evaluator\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nfunc eva"
  },
  {
    "path": "evaluator/package.go",
    "chars": 383,
    "preview": "package evaluator\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nfunc eva"
  },
  {
    "path": "evaluator/postfix.go",
    "chars": 1350,
    "preview": "package evaluator\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nfunc eva"
  },
  {
    "path": "evaluator/prefix.go",
    "chars": 1153,
    "preview": "package evaluator\n\nimport \"github.com/NuruProgramming/Nuru/object\"\n\nfunc evalMinusPrefixOperatorExpression(right object."
  },
  {
    "path": "evaluator/property.go",
    "chars": 1673,
    "preview": "package evaluator\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nfunc eva"
  },
  {
    "path": "evaluator/switch.go",
    "chars": 643,
    "preview": "package evaluator\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nfunc eva"
  },
  {
    "path": "evaluator/type.go",
    "chars": 1808,
    "preview": "package evaluator\n\nimport (\n\t\"strconv\"\n\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nfunc convertToInteger(obj object.Ob"
  },
  {
    "path": "evaluator/while.go",
    "chars": 740,
    "preview": "package evaluator\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nconst MA"
  },
  {
    "path": "examples/Astart.nr",
    "chars": 4332,
    "preview": "/*############ A*(A-star) Algorithm ##############\n             \n             By @VictorKariuki\n\n        https://github."
  },
  {
    "path": "examples/example.nr",
    "chars": 5581,
    "preview": "// basics\n\njina = \"Nuru\"\nandika(jina) // Nuru\n\n// lists\n\norodha = [1, \"pili\", kweli]\n\nnamba = [10, 20, 30]\njina = namba["
  },
  {
    "path": "examples/perceptron.nr",
    "chars": 5220,
    "preview": "tumia hisabati\n\n// Mbinu za Kupanga\n//orodhesha(kwanza, mwisho, umbali), huunda orodha ya nambari na umbali uliowekwa ka"
  },
  {
    "path": "examples/reduce.nr",
    "chars": 696,
    "preview": "fanya reduce = unda(iterator, callback, initialValue) {\n  fanya accumulator = initialValue;\n\n  kwa thamani ktk iterator "
  },
  {
    "path": "examples/sarufi.nr",
    "chars": 1031,
    "preview": "tumia mtandao\ntumia jsoni\npakeji sarufi {\n    andaa = unda(file) {\n        config = fungua(file)\n        configString = "
  },
  {
    "path": "examples/sorting_algorithm.nr",
    "chars": 1397,
    "preview": "/* \n############ Sorting Algorithm ##############\n             \n             By @VictorKariuki\n\n        https://github.c"
  },
  {
    "path": "examples/sudoku_solver.nr",
    "chars": 2639,
    "preview": "/*########### Backtracking Algorithm ##############\n            \n                By @VictorKariuki\n\n        https://gith"
  },
  {
    "path": "extensions/README.md",
    "chars": 434,
    "preview": "# Nuru Extensions For Various Editors\n\n## [VSCODE](./vscode/)\n\nNuru syntax highlighting on VSCode\n\n## [VIM](./vim)\n\nThe "
  },
  {
    "path": "extensions/vim/syntax/nuru.vim",
    "chars": 1525,
    "preview": "\" Sintaksia ya nuru kwenye programu ya \"vim\"\n\" Lugha: Nuru\n\n\" Maneno tengwa\nsyntax keyword nuruKeyword unda pakeji rudis"
  },
  {
    "path": "extensions/vscode/CHANGELOG.md",
    "chars": 231,
    "preview": "# Change Log\n\nAll notable changes to the \"nuru\" extension will be documented in this file.\n\nCheck [Keep a Changelog](htt"
  },
  {
    "path": "extensions/vscode/README.md",
    "chars": 789,
    "preview": "# Nuru VSCode Extension\n\nThis is a syntax highliting extension for Nuru on vscode. It detects `.nr` and `.sw` files.\n\n##"
  },
  {
    "path": "go.mod",
    "chars": 1791,
    "preview": "module github.com/NuruProgramming/Nuru\n\ngo 1.18\n\nrequire (\n\tgithub.com/AvicennaJr/GoPrompt v0.0.0-20230411215003-be2316d"
  },
  {
    "path": "go.sum",
    "chars": 11589,
    "preview": "github.com/AvicennaJr/GoPrompt v0.0.0-20230411215003-be2316d88e2d h1:H+Y1MQQXd83x0xC2MPOw+gFFozKTXgcW69bV80+/wpY=\ngithub"
  },
  {
    "path": "lexer/lexer.go",
    "chars": 8036,
    "preview": "// This will convert the sequence of characters into a sequence of tokens\n\npackage lexer\n\nimport (\n\t\"github.com/NuruProg"
  },
  {
    "path": "lexer/lexer_test.go",
    "chars": 3881,
    "preview": "package lexer\n\nimport (\n\t\"testing\"\n\n\t\"github.com/NuruProgramming/Nuru/token\"\n)\n\nfunc TestNextToken(t *testing.T) {\n\tinpu"
  },
  {
    "path": "main.go",
    "chars": 2094,
    "preview": "//go:build !wasm || !js\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/NuruProgramming/Nuru/repl\"\n\t\"githu"
  },
  {
    "path": "main_wasm.go",
    "chars": 1122,
    "preview": "//go:build wasm && js\n\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/NuruProgramming/Nuru/evaluator\"\n\t\"github.com/NuruProg"
  },
  {
    "path": "module/hisabati.go",
    "chars": 21650,
    "preview": "package module\n\nimport (\n\t\"math\"\n\t\"math/rand\"\n\t\"time\"\n\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nvar MathFunctions = "
  },
  {
    "path": "module/json.go",
    "chars": 2684,
    "preview": "package module\n\nimport (\n\t\"encoding/json\"\n\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nvar JsonFunctions = map[string]o"
  },
  {
    "path": "module/module.go",
    "chars": 492,
    "preview": "package module\n\nimport \"github.com/NuruProgramming/Nuru/object\"\n\nvar Mapper = map[string]*object.Module{}\n\nfunc init() {"
  },
  {
    "path": "module/net.go",
    "chars": 4910,
    "preview": "package module\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\n\t\"github.com/NuruProgramming/Nuru/object\"\n)"
  },
  {
    "path": "module/os.go",
    "chars": 1127,
    "preview": "package module\n\nimport (\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nvar OsFunctions = map"
  },
  {
    "path": "module/time.go",
    "chars": 4933,
    "preview": "package module\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/NuruProgramming/Nuru/object\"\n)\n\nvar TimeFunctions = map"
  },
  {
    "path": "object/array.go",
    "chars": 2702,
    "preview": "package object\n\nimport (\n\t\"bytes\"\n\t\"strings\"\n)\n\ntype Array struct {\n\tElements []Object\n\toffset   int\n}\n\nfunc (ao *Array)"
  },
  {
    "path": "object/at.go",
    "chars": 208,
    "preview": "package object\n\nimport \"fmt\"\n\ntype At struct {\n\tInstance *Instance\n}\n\nfunc (a *At) Type() ObjectType { return AT }\nfunc "
  },
  {
    "path": "object/bool.go",
    "chars": 372,
    "preview": "package object\n\ntype Boolean struct {\n\tValue bool\n}\n\nfunc (b *Boolean) Inspect() string {\n\tif b.Value {\n\t\treturn \"kweli\""
  },
  {
    "path": "object/break.go",
    "chars": 145,
    "preview": "package object\n\ntype Break struct{}\n\nfunc (b *Break) Type() ObjectType { return BREAK_OBJ }\nfunc (b *Break) Inspect() st"
  },
  {
    "path": "object/builtin.go",
    "chars": 236,
    "preview": "package object\n\ntype BuiltinFunction func(args ...Object) Object\n\ntype Builtin struct {\n\tFn BuiltinFunction\n}\n\nfunc (b *"
  },
  {
    "path": "object/byte.go",
    "chars": 180,
    "preview": "package object\n\ntype Byte struct {\n\tValue  []byte\n\tString string\n}\n\nfunc (b *Byte) Inspect() string  { return \"b\" + b.St"
  },
  {
    "path": "object/continue.go",
    "chars": 160,
    "preview": "package object\n\ntype Continue struct{}\n\nfunc (c *Continue) Type() ObjectType { return CONTINUE_OBJ }\nfunc (c *Continue) "
  },
  {
    "path": "object/dict.go",
    "chars": 958,
    "preview": "package object\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"sort\"\n\t\"strings\"\n)\n\ntype DictPair struct {\n\tKey   Object\n\tValue Object\n}\n\ntyp"
  },
  {
    "path": "object/environment.go",
    "chars": 705,
    "preview": "package object\n\nfunc NewEnclosedEnvironment(outer *Environment) *Environment {\n\tenv := NewEnvironment()\n\tenv.outer = out"
  },
  {
    "path": "object/error.go",
    "chars": 264,
    "preview": "//go:build !js || !wasm\npackage object\n\nimport \"fmt\"\n\ntype Error struct {\n\tMessage string\n}\n\nfunc (e *Error) Inspect() s"
  },
  {
    "path": "object/error_wasm.go",
    "chars": 278,
    "preview": "//go:build wasm && js\npackage object\n\ntype Error struct {\n\tMessage string\n}\n\nfunc (e *Error) Inspect() string {\n\t// msg "
  },
  {
    "path": "object/file.go",
    "chars": 1668,
    "preview": "package object\n\nimport (\n\t\"os\"\n)\n\ntype File struct {\n\tFilename string\n\tContent  string\n}\n\nfunc (f *File) Type() ObjectTy"
  },
  {
    "path": "object/float.go",
    "chars": 369,
    "preview": "package object\n\nimport (\n\t\"hash/fnv\"\n\t\"strconv\"\n)\n\ntype Float struct {\n\tValue float64\n}\n\nfunc (f *Float) Inspect() strin"
  },
  {
    "path": "object/function.go",
    "chars": 678,
    "preview": "package object\n\nimport (\n\t\"bytes\"\n\t\"strings\"\n\n\t\"github.com/NuruProgramming/Nuru/ast\"\n)\n\ntype Function struct {\n\tName    "
  },
  {
    "path": "object/instance.go",
    "chars": 249,
    "preview": "package object\n\nimport \"fmt\"\n\ntype Instance struct {\n\tPackage *Package\n\tEnv     *Environment\n}\n\nfunc (i *Instance) Type("
  },
  {
    "path": "object/integer.go",
    "chars": 298,
    "preview": "package object\n\nimport \"fmt\"\n\ntype Integer struct {\n\tValue int64\n}\n\nfunc (i *Integer) Inspect() string  { return fmt.Spr"
  },
  {
    "path": "object/module.go",
    "chars": 385,
    "preview": "package object\n\ntype ModuleFunction func(args []Object, defs map[string]Object) Object\n\ntype Module struct {\n\tName      "
  },
  {
    "path": "object/null.go",
    "chars": 140,
    "preview": "package object\n\ntype Null struct{}\n\nfunc (n *Null) Inspect() string  { return \"null\" }\nfunc (n *Null) Type() ObjectType "
  },
  {
    "path": "object/object.go",
    "chars": 1124,
    "preview": "package object\n\nimport (\n\t\"fmt\"\n)\n\ntype ObjectType string\n\nconst (\n\tINTEGER_OBJ      = \"NAMBA\"\n\tFLOAT_OBJ        = \"DESI"
  },
  {
    "path": "object/object_test.go",
    "chars": 586,
    "preview": "package object\n\nimport \"testing\"\n\nfunc TestStringHashKey(t *testing.T) {\n\thello1 := &String{Value: \"Hello World\"}\n\thello"
  },
  {
    "path": "object/package.go",
    "chars": 309,
    "preview": "package object\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/NuruProgramming/Nuru/ast\"\n)\n\ntype Package struct {\n\tName  *ast.Identifier\n"
  },
  {
    "path": "object/return.go",
    "chars": 199,
    "preview": "package object\n\ntype ReturnValue struct {\n\tValue Object\n}\n\nfunc (rv *ReturnValue) Inspect() string  { return rv.Value.In"
  },
  {
    "path": "object/strings.go",
    "chars": 3794,
    "preview": "package object\n\nimport (\n\t\"fmt\"\n\t\"hash/fnv\"\n\t\"strconv\"\n\t\"strings\"\n)\n\ntype String struct {\n\tValue  string\n\toffset int\n}\n\n"
  },
  {
    "path": "object/time.go",
    "chars": 2536,
    "preview": "package object\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n\t\"time\"\n)\n\ntype Time struct {\n\tTimeValue string\n}\n\nfunc (t *Time) Type() Obje"
  },
  {
    "path": "parser/arrays.go",
    "chars": 688,
    "preview": "package parser\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/token\"\n)\n\nfunc (p *Par"
  },
  {
    "path": "parser/assignEqual.go",
    "chars": 900,
    "preview": "package parser\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/NuruProgramming/Nuru/ast\"\n)\n\nfunc (p *Parser) parseAssignEqualExpression(e"
  },
  {
    "path": "parser/assignment.go",
    "chars": 1123,
    "preview": "package parser\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/NuruProgramming/Nuru/ast\"\n)\n\nfunc (p *Parser) parseAssignmentExpression(ex"
  },
  {
    "path": "parser/at.go",
    "chars": 143,
    "preview": "package parser\n\nimport \"github.com/NuruProgramming/Nuru/ast\"\n\nfunc (p *Parser) parseAt() ast.Expression {\n\treturn &ast.A"
  },
  {
    "path": "parser/boolean.go",
    "chars": 232,
    "preview": "package parser\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/token\"\n)\n\nfunc (p *Par"
  },
  {
    "path": "parser/break.go",
    "chars": 261,
    "preview": "package parser\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/token\"\n)\n\nfunc (p *Par"
  },
  {
    "path": "parser/continue.go",
    "chars": 270,
    "preview": "package parser\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/token\"\n)\n\nfunc (p *Par"
  },
  {
    "path": "parser/dict.go",
    "chars": 637,
    "preview": "package parser\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/token\"\n)\n\nfunc (p *Par"
  },
  {
    "path": "parser/dot.go",
    "chars": 1036,
    "preview": "package parser\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/token\"\n)\n\nfunc (p *Par"
  },
  {
    "path": "parser/float.go",
    "chars": 447,
    "preview": "package parser\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n\n\t\"github.com/NuruProgramming/Nuru/ast\"\n)\n\nfunc (p *Parser) parseFloatLiteral"
  },
  {
    "path": "parser/for.go",
    "chars": 2149,
    "preview": "package parser\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/token\"\n)\n\nfunc (p *Par"
  },
  {
    "path": "parser/function.go",
    "chars": 1393,
    "preview": "package parser\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/token\"\n)\n\nfunc (p *Par"
  },
  {
    "path": "parser/identifier.go",
    "chars": 191,
    "preview": "package parser\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n)\n\nfunc (p *Parser) parseIdentifier() ast.Expression {\n\t"
  },
  {
    "path": "parser/if.go",
    "chars": 911,
    "preview": "package parser\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/token\"\n)\n\nfunc (p *Par"
  },
  {
    "path": "parser/import.go",
    "chars": 534,
    "preview": "package parser\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/token\"\n)\n\nfunc (p *Par"
  },
  {
    "path": "parser/index.go",
    "chars": 366,
    "preview": "package parser\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/token\"\n)\n\nfunc (p *Par"
  },
  {
    "path": "parser/integer.go",
    "chars": 454,
    "preview": "package parser\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n\n\t\"github.com/NuruProgramming/Nuru/ast\"\n)\n\nfunc (p *Parser) parseIntegerLiter"
  },
  {
    "path": "parser/null.go",
    "chars": 152,
    "preview": "package parser\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n)\n\nfunc (p *Parser) parseNull() ast.Expression {\n\treturn"
  },
  {
    "path": "parser/package.go",
    "chars": 416,
    "preview": "package parser\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/token\"\n)\n\nfunc (p *Par"
  },
  {
    "path": "parser/parser.go",
    "chars": 8360,
    "preview": "package parser\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/lexer\"\n\t\"githu"
  },
  {
    "path": "parser/parser_test.go",
    "chars": 25357,
    "preview": "package parser\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/lex"
  },
  {
    "path": "parser/statements.go",
    "chars": 1575,
    "preview": "package parser\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/token\"\n)\n\nfunc"
  },
  {
    "path": "parser/string.go",
    "chars": 197,
    "preview": "package parser\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n)\n\nfunc (p *Parser) parseStringLiteral() ast.Expression "
  },
  {
    "path": "parser/switch.go",
    "chars": 1813,
    "preview": "package parser\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/token\"\n)\n\nfunc"
  },
  {
    "path": "parser/while.go",
    "chars": 512,
    "preview": "package parser\n\nimport (\n\t\"github.com/NuruProgramming/Nuru/ast\"\n\t\"github.com/NuruProgramming/Nuru/token\"\n)\n\nfunc (p *Par"
  },
  {
    "path": "repl/docs/en/README.md",
    "chars": 6907,
    "preview": "# NURU PROGRAMMING LANGUAGE DOCUMENTATION\n\nThis documentation is intended for people with some experience in programming"
  },
  {
    "path": "repl/docs/en/arrays.md",
    "chars": 2797,
    "preview": "# Arrays in Nuru\n\nArrays in Nuru are versatile data structures that can hold multiple items, including different types s"
  },
  {
    "path": "repl/docs/en/bool.md",
    "chars": 2534,
    "preview": "# Working with Booleans in Nuru\n\nBoolean objects in Nuru are truthy, meaning that any value is true, except tupu and sik"
  },
  {
    "path": "repl/docs/en/builtins.md",
    "chars": 1632,
    "preview": "# Built-in Functions in Nuru\n\nNuru has several built-in functions that perform specific tasks.\n\n## The andika() Function"
  },
  {
    "path": "repl/docs/en/comments.md",
    "chars": 1539,
    "preview": "# Comments in Nuru\n\nIn Nuru, you can write comments to provide explanations and documentation for your code. Comments ar"
  },
  {
    "path": "repl/docs/en/dictionaries.md",
    "chars": 2250,
    "preview": "# Dictionaries in Nuru\n\nDictionaries in Nuru, also known as \"kamusi,\" are powerful and flexible data structures that sto"
  },
  {
    "path": "repl/docs/en/files.md",
    "chars": 511,
    "preview": "# Files in Nuru\n\nNuru's ability to deal with files is primitive, and as for now it only allows you to read contents of a"
  },
  {
    "path": "repl/docs/en/for.md",
    "chars": 2325,
    "preview": "# For Loops in Nuru\n\nFor loops are a fundamental control structure in Nuru, used for iterating over iterable objects suc"
  },
  {
    "path": "repl/docs/en/function.md",
    "chars": 2355,
    "preview": "# Functions in Nuru\n\nFunctions are a fundamental part of Nuru programming, allowing you to define reusable blocks of cod"
  },
  {
    "path": "repl/docs/en/hisabati.md",
    "chars": 7198,
    "preview": "# Module Hisabati\n\nModule Hisabati is a inbuilt math module by [VictorKariuki](https://github.com/VictorKariuki).\n\nThis "
  },
  {
    "path": "repl/docs/en/identifiers.md",
    "chars": 1347,
    "preview": "# Identifiers in Nuru\n\nIdentifiers are used to name variables, functions, and other elements in your Nuru code. This pag"
  },
  {
    "path": "repl/docs/en/ifStatements.md",
    "chars": 1428,
    "preview": "# Conditional Statements in Nuru\n\nConditional statements in Nuru are used to perform different actions based on differen"
  },
  {
    "path": "repl/docs/en/json.md",
    "chars": 1185,
    "preview": "# JSON in Nuru\n\nNuru also makes it easy to deal with JSON.\n\n## Import JSONI\n\nUse the following to import the json module"
  },
  {
    "path": "repl/docs/en/keywords.md",
    "chars": 1584,
    "preview": "# KEYWORDS\n\nKeywords in Nuru are reserved words that have special meanings and cannot be used as identifiers for variabl"
  },
  {
    "path": "repl/docs/en/net.md",
    "chars": 966,
    "preview": "# HTTP with Nuru\n\nYou can access the internet via http protocol using the `mtandao` module.\n\n## Importing\n\nImport the mo"
  },
  {
    "path": "repl/docs/en/null.md",
    "chars": 777,
    "preview": "# Null (Tupu) in Nuru\n\nThe null data type in Nuru represents the absence of a value or the concept of \"nothing\" or \"empt"
  },
  {
    "path": "repl/docs/en/numbers.md",
    "chars": 1189,
    "preview": "# INTEGERS (NAMBA) AND FLOATS (DESIMALI)\n\nIntegers and floats are the basic numeric data types in Nuru, used for represe"
  },
  {
    "path": "repl/docs/en/operators.md",
    "chars": 2507,
    "preview": "# OPERATORS\nOperators are the foundation of any programming language, allowing you to perform various operations on vari"
  },
  {
    "path": "repl/docs/en/packages.md",
    "chars": 2543,
    "preview": "# Packages in Nuru\n\nYou can use third packages written in Nuru with the following conditions:\n\n- The package file MUST b"
  },
  {
    "path": "repl/docs/en/range.md",
    "chars": 1198,
    "preview": "## Range Function (mfululizo)\n\nThe `mfululizo` function generates a sequence of numbers. It can be used in loops or to c"
  },
  {
    "path": "repl/docs/en/strings.md",
    "chars": 2265,
    "preview": "# Strings in Nuru\n\nStrings are a sequence of characters that can represent text in the Nuru programming language. This p"
  },
  {
    "path": "repl/docs/en/switch.md",
    "chars": 1363,
    "preview": "# Switch Statements in Nuru\n\nSwitch statements in Nuru allow you to execute different code blocks based on the value of "
  },
  {
    "path": "repl/docs/en/time.md",
    "chars": 1531,
    "preview": "# Time in Nuru\n\n## Importing Time\n\nTo use Time in Nuru, you first have to import the `muda` module as follows:\n\n```so\ntu"
  },
  {
    "path": "repl/docs/en/while.md",
    "chars": 1213,
    "preview": "# WHILE (WAKATI)\n\nWhile loops in Nuru are used to execute a block of code repeatedly, as long as a given condition is tr"
  },
  {
    "path": "repl/docs/sw/README.md",
    "chars": 1557,
    "preview": "# NYARAKA YA LUGHA YA PROGRAMU YA NURU\n\nHii nyaraka imeandikwa ikilenga watu wenye uzoefu na kuandika au kupanga program"
  },
  {
    "path": "repl/docs/sw/arrays.md",
    "chars": 2588,
    "preview": "# Orodha Au Safu Katika Nuru\n\nSafu katika nuru ni miundo ya data ambayo inaweza kubeba vitu vingi, ikiwa ni pamoja na ai"
  },
  {
    "path": "repl/docs/sw/bools.md",
    "chars": 2658,
    "preview": "# Kufanya Kazi na Buliani Katika Nuru\n\nVitu vyote katika Nuru ni kweli, yaani thamani yoyote ni kweli isipokua tupu and "
  },
  {
    "path": "repl/docs/sw/builtins.md",
    "chars": 1737,
    "preview": "# Vitendakazi Vilivyojengwa Ndani ya Nuru\n\nNuru ina vitendakazi kadhaa vilivyojengwa ndani vinavyofanya kazi husika.\n\n##"
  },
  {
    "path": "repl/docs/sw/dictionaries.md",
    "chars": 2789,
    "preview": "# Kamusi Katika Nuru\n\nKamusi katika Nuru ni miundo ya data inayotunza jozi za funguo-thamani. Ukurasa huu unatoa maelezo"
  },
  {
    "path": "repl/docs/sw/for.md",
    "chars": 2301,
    "preview": "# Vitanzi Vya Kwa Katika Nuru\n\nVitanzi vya `kwa` ni muundo msingi wa udhibiti katika Nuru ambavyo hutumika kuzunguka vit"
  },
  {
    "path": "repl/docs/sw/functions.md",
    "chars": 2482,
    "preview": "# Undo (Functions)\n\nVitendakazi ni sehemu ya msingi ya Nuru inayokuwezesha kuainisha mapande ya msimbo yanayoweza kutumi"
  },
  {
    "path": "repl/docs/sw/identifiers.md",
    "chars": 1519,
    "preview": "# Vitambulisho katika Nuru\n\nVitambulisho hutumika kuweka majina kwenye vigezo, vitendakazi na vipengele vingine katika m"
  },
  {
    "path": "repl/docs/sw/if.md",
    "chars": 22,
    "preview": "# Kama/Sivyo (If/Else)"
  },
  {
    "path": "repl/docs/sw/keywords.md",
    "chars": 26,
    "preview": "# Maneno Muhimu (Keywords)"
  },
  {
    "path": "repl/docs/sw/maoni.md",
    "chars": 1462,
    "preview": "# Maoni Katika Nuru\n\nKatika Nuru, unaweza kuandika maoni kutoa maelezo na hati kwa kazi yako. Maoni ni mistari ya maandi"
  },
  {
    "path": "repl/docs/sw/null.md",
    "chars": 13,
    "preview": "# Tupu (Null)"
  },
  {
    "path": "repl/docs/sw/numbers.md",
    "chars": 33,
    "preview": "# Namba na Desimali (Ints/Floats)"
  },
  {
    "path": "repl/docs/sw/operators.md",
    "chars": 23,
    "preview": "# Matendaji (Operators)"
  },
  {
    "path": "repl/docs/sw/range.md",
    "chars": 1307,
    "preview": "## Kitendakazi cha Mfululizo\n\nKitendakazi cha `mfululizo` hutoa mfululizo wa nambari, sawa na kitendakazi cha `range()` "
  },
  {
    "path": "repl/docs/sw/strings.md",
    "chars": 16,
    "preview": "# Neno (Strings)"
  },
  {
    "path": "repl/docs/sw/switch.md",
    "chars": 17,
    "preview": "# Badili (Switch)"
  },
  {
    "path": "repl/docs/sw/while.md",
    "chars": 16,
    "preview": "# Wakati (While)"
  },
  {
    "path": "repl/docs.go",
    "chars": 9496,
    "preview": "package repl\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/NuruProgramming/Nuru/evaluator\"\n\t\"github.com/NuruProgramming/Nuru"
  },
  {
    "path": "repl/repl.go",
    "chars": 6823,
    "preview": "package repl\n\nimport (\n\t\"embed\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"strings\"\n\n\tprompt \"github.com/AvicennaJr/GoPrompt\"\n\t\"github.com/Nu"
  },
  {
    "path": "sh/install.sh",
    "chars": 4082,
    "preview": "#!/usr/bin/env sh\n\n# Hii ni skripti ya shell ili kusakinisha programu ya Nuru.\n# Programu zinazohitajika:\n#   - curl/wge"
  },
  {
    "path": "styles/styles.go",
    "chars": 599,
    "preview": "package styles\n\nimport \"github.com/charmbracelet/lipgloss\"\n\nvar (\n\tTitleStyle   = lipgloss.NewStyle().Margin(1, 0).Foreg"
  },
  {
    "path": "third_party/math/README.md",
    "chars": 9219,
    "preview": "# Pakeji Hesabu (Math Package)\n\nPakeji Hesabu is a math package written in pure Nuru by [VictorKariuki](https://github.c"
  },
  {
    "path": "third_party/math/hesabu.nr",
    "chars": 14094,
    "preview": "tumia hisabati\n\npakeji hesabu{\n    //CONSTRUCTOR METHOD    \n    andaa = unda() {}\n\n    // Constants\n    // π (Pi)\n    PI"
  },
  {
    "path": "third_party/math/test.nr",
    "chars": 1449,
    "preview": "tumia \"hesabu\"\n\nandika(\"abs: \",hesabu.abs(-42));\nandika(\"acos: \",hesabu.acos(0.5));\nandika(\"acosh: \",hesabu.acosh(2));\na"
  },
  {
    "path": "token/token.go",
    "chars": 2001,
    "preview": "// This is where we define our tokens\n\npackage token\n\ntype TokenType string\n\ntype Token struct {\n\tType    TokenType\n\tLit"
  }
]

// ... and 2 more files (download for full content)

About this extraction

This page contains the full source code of the AvicennaJr/Nuru GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 166 files (399.8 KB), approximately 125.8k tokens, and a symbol index with 654 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!