튜토리얼
Vais Playground Tutorial
Step-by-step guide to using the Vais Playground.
Getting Started
Step 1: Opening the Playground
- Navigate to the playground URL (or run locally with
npm run dev) - The playground loads with a default "Hello World" example
- The interface has three main sections:
- Left: Examples sidebar
- Center: Code editor
- Right: Output panel
Step 2: Understanding the Interface
Header Bar
- Logo: Shows you're in Vais Playground
- Version: Current Vais version (v1.0.0)
- GitHub Link: Opens Vais repository
- Docs Link: Opens language documentation
Sidebar
- Examples List: Click any example to load it
- Active Example: Highlighted in purple
- Keyboard Shortcuts: Quick reference at bottom
Editor Toolbar
- Example Dropdown: Another way to select examples
- Format Button: Auto-formats your code
- Clear Button: Clears the output panel
- Run Button: Compiles and executes code
Output Panel
- Status Indicator: Shows current state (Ready/Running/Success/Error)
- Output Area: Shows compilation results and program output
Step 3: Running Your First Program
-
Select an Example
- Click "Hello World" in the sidebar
- Or select it from the dropdown
-
Review the Code
# Hello World example using puts F main()->i64 { puts("Hello, Vais!") 0 } -
Run the Program
- Click the "Run" button
- Or press
Ctrl+Enter(Windows/Linux) orCmd+Enter(Mac)
-
Check the Output
- The output panel shows compilation status
- Program output appears below
- Exit code is displayed if non-zero
Learning the Language
Lesson 1: Functions
Functions in Vais start with F:
# Single-expression function
F add(a: i64, b: i64) -> i64 = a + b
# Block function
F greet(name: str) -> i64 {
puts("Hello, ")
puts(name)
0
}
# Main function (entry point)
F main() -> i64 {
result := add(5, 3)
greet("World")
0
}
Try it:
- Load the "Functions" example
- Modify the parameters
- Run and see the results
Lesson 2: Variables and Types
Vais uses := for type-inferred declarations:
F main() -> i64 {
# Type inference
x := 42 # i64
y := 3.14 # f64
flag := true # bool
# Explicit types
a: i64 = 100
b: f64 = 2.5
# Type annotations in functions
result := add(x, a)
0
}
F add(a: i64, b: i64) -> i64 = a + b
Supported Types:
- Integers:
i8,i16,i32,i64,u8,u16,u32,u64 - Floats:
f32,f64 - Boolean:
bool - String:
str - Arrays:
[T] - Custom: Structs and Enums
Lesson 3: Control Flow
If-Else (I/E keywords)
F check_number(n: i64) -> i64 {
result := I n > 0 {
puts("Positive")
1
} E I n < 0 {
puts("Negative")
-1
} E {
puts("Zero")
0
}
result
}
Ternary Operator
F max(a: i64, b: i64) -> i64 = a > b ? a : b
Try it:
- Load "Control Flow" example
- Change the conditions
- Add more branches
Lesson 4: Loops
Range Loop (L keyword)
F print_numbers() -> i64 {
# Loop from 0 to 9
L i:0..10 {
putchar(i + 48) # Convert to ASCII
putchar(32) # Space
}
putchar(10) # Newline
0
}
While-Style Loop
F countdown() -> i64 {
counter := 10
L {
I counter <= 0 { break }
putchar(counter + 48)
putchar(32)
counter -= 1
}
0
}
Loop with Continue
F skip_evens() -> i64 {
L i:0..10 {
I i % 2 == 0 { continue }
putchar(i + 48)
}
0
}
Try it:
- Load "Loops" example
- Modify the range
- Add break/continue conditions
Lesson 5: Structs (S keyword)
# Define a struct
S Point {
x: f64,
y: f64
}
# Create and use struct
F main() -> i64 {
# Create instance
p := Point { x: 3.0, y: 4.0 }
# Access fields
x_val := p.x
y_val := p.y
0
}
Methods on Structs
S Rectangle {
width: f64,
height: f64
}
# Implement methods
I Rectangle {
F area() -> f64 {
@.width * @.height
}
F perimeter() -> f64 {
2.0 * (@.width + @.height)
}
}
F main() -> i64 {
rect := Rectangle { width: 5.0, height: 3.0 }
a := rect.area()
p := rect.perimeter()
0
}
Try it:
- Load "Struct" example
- Add more fields
- Implement additional methods
Lesson 6: Enums (E keyword)
# Define enum
E Color {
Red,
Green,
Blue,
RGB(u8, u8, u8)
}
# Use enum
F main() -> i64 {
c1 := Red
c2 := RGB(255, 128, 0)
0
}
Pattern Matching (M keyword)
E Option<T> {
Some(T),
None
}
F get_or_default(opt: Option<i64>, default: i64) -> i64 {
M opt {
Some(v) => v,
None => default
}
}
F main() -> i64 {
x := Some(42)
y := None
val1 := get_or_default(x, 0) # Returns 42
val2 := get_or_default(y, 10) # Returns 10
0
}
Try it:
- Load "Enum" example
- Add more variants
- Write match expressions
Lesson 7: Self-Recursion (@)
The @ operator calls the current function recursively:
# Traditional recursion (doesn't work in Vais)
F factorial(n: i64) -> i64 {
I n <= 1 {
1
} E {
n * factorial(n - 1) # ❌ Can't call by name
}
}
# Vais self-recursion (correct)
F factorial(n: i64) -> i64 {
I n <= 1 {
1
} E {
n * @(n - 1) # ✅ Use @ operator
}
}
# Fibonacci with self-recursion
F fib(n: i64) -> i64 = n < 2 ? n : @(n-1) + @(n-2)
# Sum from 1 to n
F sum_to_n(n: i64) -> i64 = I n <= 0 { 0 } E { n + @(n-1) }
Try it:
- Load "Self Recursion" example
- Implement more recursive functions
- Try: GCD, power, factorial
Lesson 8: Generics
# Generic function
F identity<T>(x: T) -> T = x
# Generic with constraints (future)
F max<T: Ord>(a: T, b: T) -> T = a > b ? a : b
# Use generics
F main() -> i64 {
x := identity(42) # T = i64
y := identity(3.14) # T = f64
z := identity(true) # T = bool
0
}
Generic Structs
S Box<T> {
value: T
}
F main() -> i64 {
int_box := Box { value: 42 }
float_box := Box { value: 3.14 }
0
}
Try it:
- Load "Generics" example
- Create generic functions
- Use multiple type parameters
Lesson 9: Type Inference
Vais can infer types in many contexts:
F main() -> i64 {
# Infer from literal
x := 42 # i64
y := 3.14 # f64
# Infer from function return
z := add(x, 10) # i64 from add's return
# Infer from usage
arr := [1, 2, 3] # [i64]
# Infer generic types
val := identity(x) # T = i64
0
}
F add(a: i64, b: i64) -> i64 = a + b
F identity<T>(x: T) -> T = x
Try it:
- Load "Type Inference" example
- Remove type annotations
- Let the compiler infer types
Lesson 10: Operators
F test_operators() -> i64 {
# Arithmetic
a := 10 + 5 # Addition
b := 10 - 5 # Subtraction
c := 10 * 5 # Multiplication
d := 10 / 5 # Division
e := 10 % 3 # Modulo
# Comparison
eq := 5 == 5 # Equal
ne := 5 != 3 # Not equal
gt := 10 > 5 # Greater than
lt := 5 < 10 # Less than
ge := 5 >= 5 # Greater or equal
le := 5 <= 10 # Less or equal
# Logical
and := true && false
or := true || false
not := !true
# Compound assignment
x := 10
x += 5 # x = x + 5
x -= 2 # x = x - 2
x *= 3 # x = x * 3
x /= 2 # x = x / 2
0
}
Try it:
- Load "Operators" example
- Try different combinations
- Check operator precedence
Advanced Features
Comments
# Single-line comment
/*
Multi-line
comment
*/
F main() -> i64 {
# TODO: implement this
0
}
Arrays
F main() -> i64 {
# Array literal
arr := [1, 2, 3, 4, 5]
# Array type annotation
nums: [i64] = [10, 20, 30]
# Access elements
first := arr[0]
last := arr[4]
0
}
Strings
F main() -> i64 {
# String literals
greeting := "Hello, World!"
# Escape sequences
newline := "Line 1\nLine 2"
tab := "Col1\tCol2"
quote := "He said \"Hi\""
# Print strings
puts(greeting)
0
}
Tips and Tricks
1. Use the Examples
The provided examples cover most language features. Start with these before writing from scratch.
2. Format Regularly
Press Ctrl+S or click Format to keep your code clean and readable.
3. Read Error Messages
The compiler provides helpful error messages. Read them carefully to understand what went wrong.
4. Incremental Development
Build your program piece by piece:
- Start with a simple main function
- Add one feature at a time
- Run and test after each change
5. Use Comments
Document your code with comments, especially for complex logic:
# Calculate factorial using self-recursion
# Parameters:
# n: The number to calculate factorial for
# Returns:
# The factorial of n
F factorial(n: i64) -> i64 =
I n <= 1 { 1 } E { n * @(n-1) }
6. Keyboard Shortcuts
Learn the shortcuts to work faster:
Ctrl+Enter: Run codeCtrl+S: FormatCtrl+/: Toggle commentCtrl+Space: Auto-complete
7. Check Types
When in doubt about a type, the compiler will tell you if there's a mismatch.
8. Start Simple
Begin with simple programs and gradually add complexity.
Common Mistakes
1. Forgetting Return Value
# ❌ Wrong
F main() {
puts("Hello")
}
# ✅ Correct
F main() -> i64 {
puts("Hello")
0
}
2. Missing Type Annotations
# ❌ May not work
F add(a, b) = a + b
# ✅ Better
F add(a: i64, b: i64) -> i64 = a + b
3. Incorrect Recursion
# ❌ Wrong
F fib(n: i64) -> i64 = n < 2 ? n : fib(n-1) + fib(n-2)
# ✅ Correct
F fib(n: i64) -> i64 = n < 2 ? n : @(n-1) + @(n-2)
4. Mismatched Braces
# ❌ Wrong
F main() -> i64 {
I true {
puts("Test")
# Missing closing brace!
0
}
# ✅ Correct
F main() -> i64 {
I true {
puts("Test")
}
0
}
Next Steps
1. Complete All Examples
Work through each example in order to learn the language systematically.
2. Write Your Own Programs
Try implementing:
- Number guessing game
- Temperature converter
- Simple calculator
- Sorting algorithms
- Data structures (linked list, binary tree)
3. Read the Documentation
Check out the Language Specification for complete details.
4. Join the Community
- GitHub: Open issues, contribute code
- Discord: Ask questions, share projects
5. Explore Advanced Topics
- Traits and implementations
- Async/await patterns
- FFI (Foreign Function Interface)
- Performance optimization
Troubleshooting
Code Won't Run
- Check for syntax errors (red squiggles in editor)
- Ensure main function exists and returns i64
- Check that all braces are matched
- Look for typos in keywords (F, S, E, I, L, M)
Unexpected Output
- Add debug prints with puts()
- Check variable values
- Verify logic flow
- Test smaller pieces separately
Editor Issues
- Refresh the page
- Clear browser cache
- Try a different browser
- Check browser console for errors
Resources
- Language Spec: Complete language reference
- Examples: 13 working examples in the playground
- GitHub: Source code and issues
- Docs: Comprehensive documentation
Feedback
Found a bug or have a suggestion? Please:
- Open an issue on GitHub
- Include example code
- Describe expected vs actual behavior
- Mention browser and OS
Happy coding with Vais! ⚡