Skip to content

Commit a646462

Browse files
author
Leo Louvar
committed
Add built-in functions, modulo operator, map indexing; update guide and PDF
Made-with: Cursor
1 parent 3dd8b94 commit a646462

5 files changed

Lines changed: 1700 additions & 58 deletions

File tree

docs/Zixir Language complete guide.md

Lines changed: 187 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -97,16 +97,15 @@ Before we begin, it's important to understand Zixir's current capabilities:
9797
- ✅ Python FFI (module-level functions)
9898

9999
**Current Limitations:**
100-
- ⚠️ **Maps:** Can be created but indexing is limited (use Python for map operations)
101100
- ⚠️ **Loops:** While/for loops work with expressions but don't support variable assignment for accumulation
102101
- ⚠️ **Python Methods:** Only module-level functions work (e.g., `math.sqrt`), not methods (e.g., `str.lower`)
103-
- ⚠️ **Standard Library:** Limited built-ins; use engine operations or Python
104102

105103
**Recommended Approach:**
104+
- Use **built-in functions** for common operations (`length`, `to_string`, `print`, etc.)
105+
- Use **map indexing** for key-value access (`user["name"]`)
106106
- Use **engine operations** for bulk data processing (fastest)
107-
- Use **Python FFI** for complex operations and libraries
107+
- Use **Python FFI** for complex operations and external libraries
108108
- Use **recursion** or **engine operations** instead of imperative loops
109-
- Use **arrays** instead of maps for most data structures
110109

111110
---
112111

@@ -394,13 +393,18 @@ let person = {
394393
"city": "New York"
395394
}
396395
397-
# Maps can be created but accessing values via indexing
398-
# (e.g., person["name"]) is currently limited.
399-
# Use Python's dict methods for advanced map operations:
400-
# python "dict" "get" (person, "name")
396+
# Access map values with bracket indexing
397+
let name = person["name"] # "Alice"
398+
let age = person["age"] # 30
399+
let city = person["city"] # "New York"
401400
```
402401

403-
**Note:** Map support is basic in Zixir v1.0. For production use with maps, leverage Python integration.
402+
**Map operations using built-in functions:**
403+
```zixir
404+
let user = {"name": "Alice", "role": "admin"}
405+
let all_keys = keys(user) # ["name", "role"]
406+
let all_values = values(user) # ["Alice", "admin"]
407+
```
404408

405409
### Type Annotations
406410

@@ -483,19 +487,18 @@ let empty = []
483487
let nested = [[1, 2], [3, 4], [5, 6]] # Array of arrays
484488
```
485489

486-
**Getting the length (using Python):**
490+
**Getting the length:**
487491
```zixir
488492
let items = ["a", "b", "c"]
489-
let count = 3 # Hardcoded count
493+
let count = length(items) # 3
490494
```
491495

492496
**Common array patterns:**
493497
```zixir
494498
# Get first and last
495499
let arr = [10, 20, 30, 40, 50]
496500
let first = arr[0]
497-
let last = arr[4] # Hardcoded index
498-
# Note: Array length must be hardcoded or calculated using known array size
501+
let last = arr[length(arr) - 1] # 50 (dynamic last element)
499502
500503
# Slice (subset of array)
501504
let middle = [arr[1], arr[2], arr[3]] # [20, 30, 40]
@@ -538,65 +541,64 @@ let city = company["address"]["city"] # "New York"
538541

539542
**Working with Maps:**
540543

541-
Maps can be created, but accessing values is currently limited in Zixir v1.0. For production use with maps, use Python integration:
542-
543544
```zixir
544-
# Creating a map
545545
let user = {
546546
"name": "Alice Johnson",
547547
"age": 28,
548548
"email": "alice@example.com"
549549
}
550550
551-
# Accessing with Python (recommended)
552-
let name = python "operator" "getitem" (user, "name")
553-
let age = python "operator" "getitem" (user, "age")
551+
# Access values with bracket indexing
552+
let name = user["name"] # "Alice Johnson"
553+
let age = user["age"] # 28
554+
let email = user["email"] # "alice@example.com"
554555
555-
# Or use Python's dict methods
556-
let keys = python "dict" "keys" (user) # Get all keys
557-
let values = python "dict" "values" (user) # Get all values
556+
# Get all keys and values
557+
let all_keys = keys(user) # ["name", "age", "email"]
558+
let all_values = values(user) # ["Alice Johnson", 28, "alice@example.com"]
559+
let size = length(user) # 3
558560
```
559561

560-
**Note:** Direct map indexing (`user["name"]`) is not supported in Zixir v1.0. Use the Python approaches shown above.
561-
562562
### Type Conversions
563563

564-
Sometimes you need to convert between types. Zixir provides these functions:
564+
Zixir provides built-in functions for type conversion:
565565

566566
```zixir
567-
# Type conversions in Zixir:
568-
# - Integers: Just write the number (42)
569-
# - Floats: Just write the number (3.14)
570-
# - String to number: Not directly supported in v1.0
571-
# - Number to string: Use interpolation or engine operations
572-
573-
# For string representation, you can use:
567+
# Number to string
574568
let num = 42
575-
let num_str = "42" # Just write it as a string literal
569+
let num_str = to_string(num) # "42"
570+
let pi_str = to_string(3.14) # "3.14"
571+
let bool_str = to_string(true) # "true"
576572
577-
# Or use Python's built-in functions (requires __builtins__ module):
578-
# Note: Built-in functions may not be available in all Python configurations
579-
let arr_display = "[1, 2, 3]" # For display purposes
573+
# String to number
574+
let parsed_int = parse_int("42") # 42
575+
let parsed_float = parse_float("3.14") # 3.14
576+
577+
# Check types at runtime
578+
let t = type_of(42) # "Int"
579+
let t2 = type_of("hello") # "String"
580+
let t3 = type_of([1, 2, 3]) # "Array"
580581
```
581582

582-
### Real-World Example: User Profile (Using Arrays)
583+
### Real-World Example: User Profile
583584

584-
Since map indexing is limited, here's how to store user data using arrays:
585+
Maps make it easy to work with structured data:
585586

586587
```zixir
587-
# Store user data as parallel arrays
588-
let names = ["Alice", "Bob", "Charlie"]
589-
let ages = [28, 35, 42]
590-
let emails = ["alice@example.com", "bob@example.com", "charlie@example.com"]
588+
# Store user profiles as maps
589+
let user = {
590+
"name": "Alice",
591+
"age": 28,
592+
"email": "alice@example.com"
593+
}
591594
592-
# Access by index
593-
let index = 0
594-
let name = names[index] # "Alice"
595-
let age = ages[index] # 28
596-
let email = emails[index] # "alice@example.com"
595+
# Access fields with bracket indexing
596+
let name = user["name"] # "Alice"
597+
let age = user["age"] # 28
597598
598-
# Create a summary (for display, just use string literals)
599-
"User " ++ name ++ " is " ++ "28" ++ " years old"
599+
# Build a summary string
600+
let summary = "User " ++ name ++ " is " ++ to_string(age) ++ " years old"
601+
print(summary) # "User Alice is 28 years old"
600602
# Result: "User Alice is 28 years old"
601603
```
602604

@@ -638,13 +640,16 @@ let age = python "operator" "getitem" (user, "age")
638640
| `-` | Subtraction | `10 - 4` | `6` |
639641
| `*` | Multiplication | `6 * 7` | `42` |
640642
| `/` | Division | `15 / 3` | `5.0` |
643+
| `%` | Modulo (remainder) | `10 % 3` | `1` |
641644
| `-` | Negation | `-5` | `-5` |
642645

643-
**Important:** Division always returns a Float, even if the result is a whole number.
646+
**Important:** Division always returns a Float, even if the result is a whole number. Modulo returns an integer when both operands are integers.
644647

645648
```zixir
646649
10 / 2 # 5.0 (Float)
647650
10 / 3 # 3.3333333333 (Float)
651+
10 % 3 # 1 (remainder)
652+
17 % 5 # 2
648653
```
649654

650655
### Comparison Operators
@@ -714,7 +719,7 @@ Just like in math, some operations happen before others:
714719
```
715720
1. Parentheses: ( )
716721
2. Unary: -, !
717-
3. Multiplication/Division: *, /
722+
3. Multiplication/Division/Modulo: *, /, %
718723
4. Addition/Subtraction: +, -
719724
5. Comparison: <, >, <=, >=
720725
6. Equality: ==, !=
@@ -784,6 +789,102 @@ let in_range = x >= min && x <= max # true
784789

785790
---
786791

792+
## 6b. Built-in Functions
793+
794+
Zixir provides a set of built-in functions for common operations. These are always available without imports.
795+
796+
### Output
797+
798+
| Function | Description | Example | Result |
799+
|----------|-------------|---------|--------|
800+
| `print(args...)` | Print values to output | `print("Hello", 42)` | `"Hello 42"` |
801+
802+
```zixir
803+
print("Hello, World!")
804+
print("Value:", 42)
805+
print("Sum:", 2 + 3)
806+
```
807+
808+
### Type Conversion
809+
810+
| Function | Description | Example | Result |
811+
|----------|-------------|---------|--------|
812+
| `to_string(val)` | Convert any value to string | `to_string(42)` | `"42"` |
813+
| `parse_int(str)` | Parse string to integer | `parse_int("42")` | `42` |
814+
| `parse_float(str)` | Parse string to float | `parse_float("3.14")` | `3.14` |
815+
| `type_of(val)` | Get the type name as string | `type_of(42)` | `"Int"` |
816+
817+
```zixir
818+
let n = 42
819+
let s = to_string(n) # "42"
820+
let greeting = "Number: " ++ s # "Number: 42"
821+
822+
let parsed = parse_int("100") # 100
823+
let t = type_of(parsed) # "Int"
824+
```
825+
826+
### Collection Functions
827+
828+
| Function | Description | Example | Result |
829+
|----------|-------------|---------|--------|
830+
| `length(val)` | Get length of array, string, or map | `length([1,2,3])` | `3` |
831+
| `head(list)` | Get first element | `head([1,2,3])` | `1` |
832+
| `tail(list)` | Get all elements except first | `tail([1,2,3])` | `[2,3]` |
833+
| `push(list, val)` | Append element to array | `push([1,2], 3)` | `[1,2,3]` |
834+
| `reverse(val)` | Reverse array or string | `reverse([1,2,3])` | `[3,2,1]` |
835+
| `contains(col, val)` | Check if collection contains value | `contains([1,2,3], 2)` | `true` |
836+
| `range(a, b)` | Generate array from a to b | `range(1, 5)` | `[1,2,3,4,5]` |
837+
| `keys(map)` | Get all keys from a map | `keys({"a": 1})` | `["a"]` |
838+
| `values(map)` | Get all values from a map | `values({"a": 1})` | `[1]` |
839+
840+
```zixir
841+
let arr = [10, 20, 30, 40, 50]
842+
let len = length(arr) # 5
843+
let first = head(arr) # 10
844+
let rest = tail(arr) # [20, 30, 40, 50]
845+
let extended = push(arr, 60) # [10, 20, 30, 40, 50, 60]
846+
847+
let nums = range(1, 10) # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
848+
let has_five = contains(nums, 5) # true
849+
```
850+
851+
### String Functions
852+
853+
| Function | Description | Example | Result |
854+
|----------|-------------|---------|--------|
855+
| `upper(str)` | Convert to uppercase | `upper("hello")` | `"HELLO"` |
856+
| `lower(str)` | Convert to lowercase | `lower("HELLO")` | `"hello"` |
857+
| `trim(str)` | Remove leading/trailing whitespace | `trim(" hi ")` | `"hi"` |
858+
| `split(str, sep)` | Split string by separator | `split("a-b-c", "-")` | `["a","b","c"]` |
859+
| `join(list, sep)` | Join array into string | `join(["a","b"], "-")` | `"a-b"` |
860+
| `reverse(str)` | Reverse a string | `reverse("abc")` | `"cba"` |
861+
| `contains(str, sub)` | Check if string contains substring | `contains("hello", "ell")` | `true` |
862+
| `length(str)` | Get string length | `length("hello")` | `5` |
863+
864+
```zixir
865+
let text = " Hello, World! "
866+
let cleaned = trim(text) # "Hello, World!"
867+
let shouted = upper(cleaned) # "HELLO, WORLD!"
868+
let words = split(cleaned, " ") # ["Hello,", "World!"]
869+
let joined = join(words, "-") # "Hello,-World!"
870+
```
871+
872+
### Math Functions
873+
874+
| Function | Description | Example | Result |
875+
|----------|-------------|---------|--------|
876+
| `abs(n)` | Absolute value | `abs(-5)` | `5` |
877+
| `min(a, b)` | Minimum of two numbers | `min(3, 7)` | `3` |
878+
| `max(a, b)` | Maximum of two numbers | `max(3, 7)` | `7` |
879+
880+
```zixir
881+
let diff = abs(-10) # 10
882+
let smaller = min(5, 3) # 3
883+
let bigger = max(5, 3) # 5
884+
```
885+
886+
---
887+
787888
## 7. Control Flow
788889

789890
Control flow lets your program make decisions and repeat actions.
@@ -2298,7 +2399,7 @@ object.field
22982399
| `[]` | 1 | Indexing |
22992400
| `.` | 1 | Field access |
23002401
| `-` `!` | 2 | Unary negation, not |
2301-
| `*` `/` | 3 | Multiplication, division |
2402+
| `*` `/` `%` | 3 | Multiplication, division, modulo |
23022403
| `+` `-` | 4 | Addition, subtraction |
23032404
| `++` | 4 | Concatenation |
23042405
| `<` `>` `<=` `>=` | 5 | Comparison |
@@ -2365,7 +2466,7 @@ const PI = 3.14159 # Compile-time constant
23652466
### Operators
23662467
```zixir
23672468
# Arithmetic
2368-
+ - * /
2469+
+ - * / %
23692470
23702471
# Comparison
23712472
== != < > <= >=
@@ -2375,18 +2476,48 @@ const PI = 3.14159 # Compile-time constant
23752476
23762477
# Other
23772478
++ # String/array concatenation
2378-
[] # Array indexing (arrays only, not maps)
2479+
[] # Array/map indexing
2480+
```
2481+
2482+
### Built-in Functions
2483+
```zixir
2484+
# Output
2485+
print("Hello", value)
2486+
2487+
# Type conversion
2488+
to_string(42) # "42"
2489+
parse_int("42") # 42
2490+
parse_float("3.14") # 3.14
2491+
type_of(value) # "Int", "String", etc.
2492+
2493+
# Collections
2494+
length(arr) # array/string/map length
2495+
head(arr) # first element
2496+
tail(arr) # all except first
2497+
push(arr, val) # append
2498+
reverse(arr) # reverse
2499+
contains(arr, val) # membership check
2500+
range(1, 10) # generate array
2501+
keys(map) # map keys
2502+
values(map) # map values
2503+
2504+
# Strings
2505+
upper(str) lower(str) trim(str)
2506+
split(str, sep) join(arr, sep)
2507+
2508+
# Math
2509+
abs(n) min(a, b) max(a, b)
23792510
```
23802511

23812512
### Control Flow
23822513
```zixir
23832514
# If/else
23842515
if condition: expr else: expr
23852516
2386-
# While loop (expression-oriented, no assignment in body)
2517+
# While loop
23872518
while condition: expr
23882519
2389-
# For loop (expression-oriented, no assignment in body)
2520+
# For loop
23902521
for item in list: expr
23912522
23922523
# Pattern matching
@@ -2396,8 +2527,6 @@ match value {
23962527
}
23972528
```
23982529

2399-
**Note:** While/for loops in Zixir are expression-oriented. They don't support variable assignment within the loop body. Use engine operations or recursion for iteration with accumulation.
2400-
24012530
### Functions
24022531
```zixir
24032532
# Named function
229 KB
Binary file not shown.

0 commit comments

Comments
 (0)