1344 lines
38 KiB
Plaintext
1344 lines
38 KiB
Plaintext
===============================================================================
|
|
THE NUMBRELLA PROJECT — Syntax Guide
|
|
===============================================================================
|
|
|
|
Copyright (C) 2026 Sixten Björling
|
|
All rights reserved.
|
|
|
|
A syntax reference for the three primary languages used in the Numbrella
|
|
ecosystem: Python (≥ 3.10), Go, and C/C++ with LLVM/Clang/Clang++.
|
|
|
|
===============================================================================
|
|
TABLE OF CONTENTS
|
|
===============================================================================
|
|
PART I — PYTHON (≥ 3.10)
|
|
PART II — GO
|
|
PART III — C / C++ (C17 / C++20) with Clang/Clang++ & LLVM
|
|
|
|
===============================================================================
|
|
PART I — PYTHON (≥ 3.10)
|
|
===============================================================================
|
|
|
|
--- 1.1 Basic Structure ------------------------------------------------
|
|
|
|
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
"""Module docstring."""
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
CONSTANT = 42
|
|
|
|
def main() -> None:
|
|
"""Entry point."""
|
|
print("Hello, Numbrella.")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
|
|
--- 1.2 Variables & Types ----------------------------------------------
|
|
|
|
x: int = 42 # Integer
|
|
y: float = 3.14 # Float
|
|
z: complex = 1 + 2j # Complex
|
|
name: str = "Numbrella" # String
|
|
flag: bool = True # Boolean
|
|
nothing: None = None # None
|
|
|
|
# F-strings (Python ≥ 3.6)
|
|
s = f"Value: {x}, Name: {name}"
|
|
|
|
# Triple-quoted strings
|
|
multiline = """Line 1
|
|
Line 2"""
|
|
|
|
--- 1.3 Collections ----------------------------------------------------
|
|
|
|
# List (mutable, ordered)
|
|
items: list[int] = [1, 2, 3]
|
|
items.append(4)
|
|
items.pop()
|
|
first = items[0]
|
|
|
|
# Tuple (immutable, ordered)
|
|
coords: tuple[int, int] = (10, 20)
|
|
x, y = coords # Unpacking
|
|
|
|
# Set (mutable, unordered, unique)
|
|
tags: set[str] = {"audio", "dsp"}
|
|
tags.add("midi")
|
|
|
|
# Dictionary (mutable, key-value)
|
|
config: dict[str, Any] = {"host": "localhost", "port": 8080}
|
|
config["debug"] = True
|
|
value = config.get("missing", "default")
|
|
|
|
# Comprehensions
|
|
squares = [n ** 2 for n in range(10) if n % 2 == 0]
|
|
mapping = {k: k.upper() for k in ["a", "b", "c"]}
|
|
|
|
--- 1.4 Control Flow ---------------------------------------------------
|
|
|
|
# If / elif / else
|
|
if x > 0:
|
|
result = "positive"
|
|
elif x < 0:
|
|
result = "negative"
|
|
else:
|
|
result = "zero"
|
|
|
|
# Match / case (Python ≥ 3.10)
|
|
match value:
|
|
case 0:
|
|
print("Zero")
|
|
case 1 | 2:
|
|
print("One or two")
|
|
case str(s):
|
|
print(f"String: {s}")
|
|
case [first, *rest]:
|
|
print(f"List starting with {first}")
|
|
case {"type": "audio", "rate": r}:
|
|
print(f"Audio at {r} Hz")
|
|
case _:
|
|
print("Unknown")
|
|
|
|
# While
|
|
while condition:
|
|
do_work()
|
|
if done:
|
|
break
|
|
|
|
# For
|
|
for item in items:
|
|
process(item)
|
|
|
|
for i, item in enumerate(items):
|
|
print(f"{i}: {item}")
|
|
|
|
for key, val in config.items():
|
|
print(f"{key} = {val}")
|
|
|
|
--- 1.5 Functions -------------------------------------------------------
|
|
|
|
def add(a: int, b: int) -> int:
|
|
"""Add two integers."""
|
|
return a + b
|
|
|
|
# Default arguments
|
|
def greet(name: str = "World") -> str:
|
|
return f"Hello, {name}."
|
|
|
|
# Variadic arguments
|
|
def log(*messages: str, **kwargs: Any) -> None:
|
|
level = kwargs.get("level", "INFO")
|
|
for msg in messages:
|
|
print(f"[{level}] {msg}")
|
|
|
|
# Lambda
|
|
square = lambda n: n * n
|
|
|
|
# Decorator
|
|
from functools import wraps
|
|
|
|
def timer(func):
|
|
@wraps(func)
|
|
def wrapper(*args, **kwargs):
|
|
import time
|
|
start = time.perf_counter()
|
|
result = func(*args, **kwargs)
|
|
elapsed = time.perf_counter() - start
|
|
print(f"{func.__name__} took {elapsed:.4f}s")
|
|
return result
|
|
return wrapper
|
|
|
|
@timer
|
|
def heavy_computation() -> int:
|
|
return sum(range(1_000_000))
|
|
|
|
--- 1.6 Classes ---------------------------------------------------------
|
|
|
|
from dataclasses import dataclass
|
|
|
|
@dataclass
|
|
class AudioClip:
|
|
path: str
|
|
sample_rate: int = 44100
|
|
channels: int = 2
|
|
|
|
def duration_ms(self) -> float:
|
|
"""Read from file and compute duration."""
|
|
...
|
|
|
|
# Traditional class
|
|
class Buffer:
|
|
def __init__(self, size: int) -> None:
|
|
self._size = size
|
|
self._data = bytearray(size)
|
|
|
|
def __len__(self) -> int:
|
|
return self._size
|
|
|
|
def __getitem__(self, index: int) -> int:
|
|
return self._data[index]
|
|
|
|
def __enter__(self):
|
|
return self
|
|
|
|
def __exit__(self, *args):
|
|
self._data.clear()
|
|
|
|
--- 1.7 Exceptions ------------------------------------------------------
|
|
|
|
try:
|
|
risky_operation()
|
|
except ValueError as e:
|
|
print(f"Bad value: {e}")
|
|
except (IOError, OSError):
|
|
print("I/O failure")
|
|
else:
|
|
print("No exception raised") # Runs only on success
|
|
finally:
|
|
cleanup() # Always runs
|
|
|
|
# Raise
|
|
raise RuntimeError("Something went wrong")
|
|
|
|
# Custom exception
|
|
class NumbrellaError(Exception):
|
|
"""Base exception for Numbrella."""
|
|
|
|
--- 1.8 Context Managers ------------------------------------------------
|
|
|
|
with open("file.txt", "r") as f:
|
|
data = f.read()
|
|
|
|
from contextlib import contextmanager
|
|
|
|
@contextmanager
|
|
def temporary_path(base: Path):
|
|
path = base / "temp"
|
|
path.mkdir(exist_ok=True)
|
|
try:
|
|
yield path
|
|
finally:
|
|
import shutil
|
|
shutil.rmtree(path)
|
|
|
|
--- 1.9 Async / Await ---------------------------------------------------
|
|
|
|
import asyncio
|
|
|
|
async def fetch_data(url: str) -> str:
|
|
async with aiohttp.ClientSession() as session:
|
|
async with session.get(url) as resp:
|
|
return await resp.text()
|
|
|
|
async def main() -> None:
|
|
tasks = [fetch_data(u) for u in urls]
|
|
results = await asyncio.gather(*tasks)
|
|
|
|
asyncio.run(main())
|
|
|
|
--- 1.10 Modules & Packages ----------------------------------------------
|
|
|
|
# Relative imports (inside a package)
|
|
from . import sibling
|
|
from .sibling import SomeClass
|
|
from ..parent_pkg import util
|
|
|
|
# Conditional import
|
|
try:
|
|
import orjson as json
|
|
except ImportError:
|
|
import json
|
|
|
|
--- 1.11 Type Hints (Advanced) -------------------------------------------
|
|
|
|
from typing import Generic, TypeVar, Protocol, Literal, Final
|
|
|
|
T = TypeVar("T")
|
|
|
|
class Stack(Generic[T]):
|
|
def push(self, item: T) -> None: ...
|
|
def pop(self) -> T: ...
|
|
|
|
class Renderable(Protocol):
|
|
def render(self) -> str: ...
|
|
|
|
Mode = Literal["read", "write", "append"]
|
|
MAX_CONNECTIONS: Final = 256
|
|
|
|
===============================================================================
|
|
PART II — GO
|
|
===============================================================================
|
|
|
|
--- 2.1 Basic Structure ------------------------------------------------
|
|
|
|
// +build !wasm ← build constraint (old)
|
|
//go:build !wasm ← build constraint (Go ≥ 1.17)
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
)
|
|
|
|
func main() {
|
|
fmt.Println("Hello, Numbrella.")
|
|
os.Exit(0)
|
|
}
|
|
|
|
--- 2.2 Variables & Types ----------------------------------------------
|
|
|
|
var name string = "Numbrella"
|
|
var version = "0.1.0" // Type inferred
|
|
var x, y int = 10, 20 // Multiple
|
|
|
|
// Short declaration (inside functions only)
|
|
count := 0
|
|
message := fmt.Sprintf("Count: %d", count)
|
|
|
|
// Blanks
|
|
_, err := doThing()
|
|
|
|
// Constants
|
|
const MaxRetries = 3
|
|
const (
|
|
StatusOK = 200
|
|
StatusError = 500
|
|
)
|
|
|
|
// Iota enumerator
|
|
const (
|
|
LevelDebug = iota // 0
|
|
LevelInfo // 1
|
|
LevelWarn // 2
|
|
LevelError // 3
|
|
)
|
|
|
|
// Basic types
|
|
var (
|
|
i int = 42
|
|
u uint = 100
|
|
f64 float64 = 3.1415
|
|
f32 float32 = 2.718
|
|
b bool = true
|
|
s string = "hello"
|
|
r rune = '✓' // Unicode code point (int32)
|
|
by byte = 255 // uint8
|
|
)
|
|
|
|
--- 2.3 Composite Types ------------------------------------------------
|
|
|
|
// Array (fixed size, value type)
|
|
var arr [4]int = [4]int{1, 2, 3, 4}
|
|
arr[0] = 10
|
|
|
|
// Slice (dynamic, reference type)
|
|
items := []int{1, 2, 3}
|
|
items = append(items, 4, 5)
|
|
sub := items[1:3] // [2, 3]
|
|
copied := make([]int, len(items))
|
|
copy(copied, items)
|
|
|
|
// Map
|
|
config := map[string]any{
|
|
"host": "localhost",
|
|
"port": 8080,
|
|
}
|
|
config["debug"] = true
|
|
val, ok := config["missing"] // ok == false if key absent
|
|
delete(config, "debug")
|
|
|
|
// Struct
|
|
type AudioClip struct {
|
|
Path string
|
|
SampleRate int
|
|
Channels int
|
|
_ struct{} // Prevent unkeyed literals
|
|
}
|
|
|
|
clip := AudioClip{
|
|
Path: "/assets/sound.wav",
|
|
SampleRate: 44100,
|
|
Channels: 2,
|
|
}
|
|
|
|
// Pointer
|
|
ptr := &clip
|
|
ptr.SampleRate = 48000 // Auto-dereferenced
|
|
|
|
// Interface
|
|
type Renderer interface {
|
|
Render() string
|
|
}
|
|
|
|
func RenderAll(renderers []Renderer) {
|
|
for _, r := range renderers {
|
|
fmt.Println(r.Render())
|
|
}
|
|
}
|
|
|
|
--- 2.4 Control Flow ---------------------------------------------------
|
|
|
|
// If (with optional init statement)
|
|
if val, ok := config["port"]; ok {
|
|
fmt.Printf("Port: %v\n", val)
|
|
} else if cfg := loadDefault(); cfg != nil {
|
|
fmt.Println("Using defaults")
|
|
} else {
|
|
fmt.Println("No config available")
|
|
}
|
|
|
|
// Switch (no fallthrough by default)
|
|
switch level := getLevel(); level {
|
|
case LevelDebug:
|
|
fmt.Println("Debug")
|
|
case LevelInfo, LevelWarn: // Multiple cases
|
|
fmt.Println("Info/Warn")
|
|
default:
|
|
fmt.Printf("Unknown: %d\n", level)
|
|
}
|
|
|
|
// Switch without expression = if/else chain
|
|
switch {
|
|
case x < 0:
|
|
fmt.Println("negative")
|
|
case x == 0:
|
|
fmt.Println("zero")
|
|
default:
|
|
fmt.Println("positive")
|
|
}
|
|
|
|
// Type switch
|
|
switch v := data.(type) {
|
|
case string:
|
|
fmt.Printf("string: %s\n", v)
|
|
case int:
|
|
fmt.Printf("int: %d\n", v)
|
|
case nil:
|
|
fmt.Println("nil")
|
|
}
|
|
|
|
// For (Go's only loop construct)
|
|
for i := 0; i < 10; i++ { // C-style
|
|
...
|
|
}
|
|
for condition { // While
|
|
...
|
|
}
|
|
for { // Infinite
|
|
if done() { break }
|
|
}
|
|
for idx, item := range items { // Range over slice
|
|
...
|
|
}
|
|
for key, val := range config { // Range over map
|
|
...
|
|
}
|
|
|
|
--- 2.5 Functions -------------------------------------------------------
|
|
|
|
func add(a, b int) int {
|
|
return a + b
|
|
}
|
|
|
|
// Multiple return values
|
|
func divide(a, b float64) (float64, error) {
|
|
if b == 0 {
|
|
return 0, fmt.Errorf("division by zero")
|
|
}
|
|
return a / b, nil
|
|
}
|
|
|
|
// Named return values (naked return)
|
|
func parse(s string) (result int, err error) {
|
|
result, err = strconv.Atoi(s)
|
|
return // Naked return
|
|
}
|
|
|
|
// Variadic
|
|
func log(level string, messages ...string) {
|
|
for _, msg := range messages {
|
|
fmt.Printf("[%s] %s\n", level, msg)
|
|
}
|
|
}
|
|
|
|
// Defer (LIFO, runs on function exit)
|
|
func readFile(path string) ([]byte, error) {
|
|
f, err := os.Open(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer f.Close()
|
|
return io.ReadAll(f)
|
|
}
|
|
|
|
// Closures
|
|
counter := func() func() int {
|
|
n := 0
|
|
return func() int {
|
|
n++
|
|
return n
|
|
}
|
|
}()
|
|
|
|
--- 2.6 Methods & Interfaces -------------------------------------------
|
|
|
|
type Buffer struct {
|
|
data []byte
|
|
}
|
|
|
|
// Value receiver (read-only, copied)
|
|
func (b Buffer) Len() int {
|
|
return len(b.data)
|
|
}
|
|
|
|
// Pointer receiver (can mutate)
|
|
func (b *Buffer) Write(p []byte) (int, error) {
|
|
b.data = append(b.data, p...)
|
|
return len(p), nil
|
|
}
|
|
|
|
// Interface compliance is implicit (structural typing)
|
|
var w io.Writer = &Buffer{}
|
|
|
|
// Interface composition
|
|
type ReadWriteCloser interface {
|
|
io.Reader
|
|
io.Writer
|
|
io.Closer
|
|
}
|
|
|
|
// Empty interface = any type
|
|
var anything any = 42 // (any is an alias for interface{} in Go ≥ 1.18)
|
|
|
|
--- 2.7 Generics (Go ≥ 1.18) --------------------------------------------
|
|
|
|
// Generic function
|
|
func Map[T, U any](items []T, fn func(T) U) []U {
|
|
result := make([]U, len(items))
|
|
for i, item := range items {
|
|
result[i] = fn(item)
|
|
}
|
|
return result
|
|
}
|
|
|
|
// Generic type with constraint
|
|
type Number interface {
|
|
~int | ~int64 | ~float64
|
|
}
|
|
|
|
func Sum[N Number](values []N) N {
|
|
var total N
|
|
for _, v := range values {
|
|
total += v
|
|
}
|
|
return total
|
|
}
|
|
|
|
// Generic struct
|
|
type Stack[T any] struct {
|
|
items []T
|
|
}
|
|
func (s *Stack[T]) Push(item T) { s.items = append(s.items, item) }
|
|
func (s *Stack[T]) Pop() T {
|
|
item := s.items[len(s.items)-1]
|
|
s.items = s.items[:len(s.items)-1]
|
|
return item
|
|
}
|
|
|
|
--- 2.8 Goroutines & Channels ------------------------------------------
|
|
|
|
// Goroutine
|
|
go func() {
|
|
doWork()
|
|
}()
|
|
|
|
// Channel (unbuffered)
|
|
ch := make(chan int)
|
|
go func() { ch <- 42 }()
|
|
val := <-ch
|
|
|
|
// Buffered channel
|
|
ch := make(chan string, 10)
|
|
|
|
// Select (multiplex channels)
|
|
select {
|
|
case msg := <-ch:
|
|
fmt.Println(msg)
|
|
case ch2 <- data:
|
|
fmt.Println("sent")
|
|
case <-time.After(5 * time.Second):
|
|
fmt.Println("timeout")
|
|
default:
|
|
fmt.Println("no activity")
|
|
}
|
|
|
|
// Directional channels
|
|
func producer(out chan<- int) { out <- 1 }
|
|
func consumer(in <-chan int) { _ = <-in }
|
|
|
|
// Close + range
|
|
close(ch)
|
|
for item := range ch { ... }
|
|
|
|
// sync.WaitGroup
|
|
var wg sync.WaitGroup
|
|
for i := 0; i < 5; i++ {
|
|
wg.Add(1)
|
|
go func(n int) {
|
|
defer wg.Done()
|
|
process(n)
|
|
}(i)
|
|
}
|
|
wg.Wait()
|
|
|
|
--- 2.9 Error Handling -------------------------------------------------
|
|
|
|
// Sentinel errors
|
|
if errors.Is(err, io.EOF) { ... }
|
|
|
|
// Error wrapping (Go ≥ 1.13)
|
|
if err != nil {
|
|
return fmt.Errorf("open config: %w", err)
|
|
}
|
|
var configErr *ConfigError
|
|
if errors.As(err, &configErr) { ... }
|
|
|
|
--- 2.10 Embedding -------------------------------------------------------
|
|
|
|
type Logger struct{}
|
|
|
|
func (l Logger) Log(msg string) { fmt.Println(msg) }
|
|
|
|
type Service struct {
|
|
Logger // Embedding → Service.Log() promoted
|
|
Name string
|
|
}
|
|
|
|
// Interface embedding
|
|
type FileSystem interface {
|
|
fs.FS
|
|
fs.ReadDirFS
|
|
}
|
|
|
|
--- 2.11 Package Layout --------------------------------------------------
|
|
|
|
myservice/
|
|
├── main.go // package main
|
|
├── internal/ // Not importable outside the module
|
|
│ ├── db/
|
|
│ └── auth/
|
|
├── pkg/ // Public API (consumable by other modules)
|
|
│ └── client/
|
|
├── cmd/ // Sub-commands
|
|
│ ├── serve/
|
|
│ └── migrate/
|
|
├── go.mod
|
|
└── go.sum
|
|
|
|
--- 2.12 cgo (C Interop) -------------------------------------------------
|
|
|
|
/*
|
|
#cgo CFLAGS: -I${SRCDIR}/../../Libraries
|
|
#cgo LDFLAGS: -L${SRCDIR}/../../Libraries/FilesLib -lFilesLib
|
|
#include "FilesLib/header.h"
|
|
#include <stdlib.h>
|
|
*/
|
|
import "C"
|
|
import "unsafe"
|
|
|
|
func CallC() {
|
|
cs := C.CString("data from Go")
|
|
defer C.free(unsafe.Pointer(cs))
|
|
C.process_data(cs)
|
|
}
|
|
|
|
===============================================================================
|
|
PART III — C / C++ (C17 / C++20) WITH CLANG/CLANG++ & LLVM
|
|
===============================================================================
|
|
|
|
--- 3.1 Compiler Invocation (Clang / Clang++) --------------------------
|
|
|
|
# C (C17)
|
|
clang -std=c17 -Wall -Wextra -Wpedantic -O2 -c source.c -o source.o
|
|
|
|
# C++ (C++20)
|
|
clang++ -std=c++20 -Wall -Wextra -Wpedantic -O2 -c source.cpp -o source.o
|
|
|
|
# Linking
|
|
clang++ source.o -lSDL3 -lSDL3_image -o myapp
|
|
|
|
# Full build pipeline
|
|
clang++ -std=c++20 -O2 main.cpp app.cpp -o app
|
|
|
|
# LLVM IR output (intermediate representation)
|
|
clang++ -std=c++20 -S -emit-llvm source.cpp -o source.ll
|
|
|
|
# LLVM bitcode
|
|
clang++ -std=c++20 -c -emit-llvm source.cpp -o source.bc
|
|
|
|
# Assembly output
|
|
clang++ -std=c++20 -S source.cpp -o source.s
|
|
|
|
# Preprocessor output
|
|
clang++ -std=c++20 -E source.cpp -o source.i
|
|
|
|
# Sanitizers
|
|
clang++ -std=c++20 -fsanitize=address -g source.cpp # AddressSanitizer
|
|
clang++ -std=c++20 -fsanitize=undefined -g source.cpp # UBSan
|
|
clang++ -std=c++20 -fsanitize=memory -g source.cpp # MemorySanitizer
|
|
|
|
# LTO (Link-Time Optimization)
|
|
clang++ -std=c++20 -flto=thin -O2 source.cpp -o app # ThinLTO
|
|
clang++ -std=c++20 -flto=full -O2 source.cpp -o app # Full LTO
|
|
|
|
# Profiling
|
|
clang++ -std=c++20 -fprofile-instr-generate source.cpp -o app
|
|
./app # Produces default.profraw
|
|
llvm-profdata merge default.profraw -o default.profdata
|
|
clang++ -std=c++20 -fprofile-instr-use=default.profdata -O2 source.cpp
|
|
|
|
# Modules (C++20)
|
|
clang++ -std=c++20 -fmodules -fbuiltin-module-map source.cpp
|
|
|
|
--- 3.2 Basic Structure -------------------------------------------------
|
|
|
|
// ===== C =====
|
|
#include <stdio.h>
|
|
#include "mylib.h"
|
|
|
|
#define BUFFER_SIZE 256
|
|
|
|
int main(int argc, char *argv[]) {
|
|
printf("Hello, Numbrella.\n");
|
|
return 0;
|
|
}
|
|
|
|
// ===== C++ =====
|
|
#include <print> // C++23; use <iostream> or <cstdio> for C++20
|
|
#include "mylib.h"
|
|
|
|
constexpr size_t BUFFER_SIZE = 256;
|
|
|
|
auto main(int argc, char *argv[]) -> int {
|
|
std::println("Hello, Numbrella.");
|
|
return 0;
|
|
}
|
|
|
|
--- 3.3 Preprocessor (C / C++ Shared) -----------------------------------
|
|
|
|
// Include guards (C; prefer #pragma once in this project)
|
|
#ifndef MYLIB_H
|
|
#define MYLIB_H
|
|
// ... declarations ...
|
|
#endif
|
|
|
|
// #pragma once (C / C++, supported by all modern compilers)
|
|
#pragma once
|
|
|
|
// Conditional compilation
|
|
#ifdef _WIN32
|
|
#define PLATFORM "windows"
|
|
#elif defined(__APPLE__)
|
|
#define PLATFORM "macos"
|
|
#elif defined(__linux__)
|
|
#define PLATFORM "linux"
|
|
#endif
|
|
|
|
// Macros
|
|
#define SQUARE(x) ((x) * (x))
|
|
#define STRINGIFY(s) #s
|
|
#define CONCAT(a, b) a ## b
|
|
|
|
// Diagnostic pragmas (Clang/GCC)
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wunused-variable"
|
|
int unused = 0;
|
|
#pragma clang diagnostic pop
|
|
|
|
--- 3.4 C Syntax (C17) --------------------------------------------------
|
|
|
|
// ---- Types ----
|
|
_Bool flag = 1; // Boolean (stdbool.h → bool)
|
|
char ch = 'A';
|
|
int n = 42;
|
|
long ln = 1000000L;
|
|
long long lln = 99999999999LL;
|
|
float f = 3.14f;
|
|
double d = 2.7182818;
|
|
size_t sz = sizeof(int);
|
|
|
|
// Fixed-width (stdint.h)
|
|
#include <stdint.h>
|
|
int8_t i8 = -128;
|
|
uint32_t u32 = 0xDEADBEEF;
|
|
|
|
// ---- Arrays ----
|
|
int arr[4] = {1, 2, 3, 4};
|
|
int arr2[] = {1, 2, 3}; // Size deduced: 3
|
|
int matrix[2][3] = {{1,2,3}, {4,5,6}};
|
|
|
|
// ---- Strings ----
|
|
char str[] = "Numbrella"; // Mutable
|
|
const char *msg = "immutable"; // String literal
|
|
|
|
// ---- Structs ----
|
|
struct Point {
|
|
int x;
|
|
int y;
|
|
};
|
|
struct Point p = {.x = 10, .y = 20}; // Designated initializer (C99)
|
|
|
|
// Typedef
|
|
typedef struct {
|
|
float real;
|
|
float imag;
|
|
} Complex;
|
|
|
|
// ---- Unions ----
|
|
union Value {
|
|
int i;
|
|
float f;
|
|
char c;
|
|
};
|
|
|
|
// ---- Enums ----
|
|
enum Status { STATUS_OK = 200, STATUS_NOT_FOUND = 404 };
|
|
|
|
// ---- Pointers ----
|
|
int a = 42;
|
|
int *p = &a;
|
|
*p = 100;
|
|
|
|
void *vp = p; // Void pointer (type-erased)
|
|
int *ip = (int *)vp; // Cast back
|
|
|
|
// Function pointer
|
|
typedef int (*operation)(int, int);
|
|
int add(int a, int b) { return a + b; }
|
|
operation op = add;
|
|
int result = op(3, 4); // result == 7
|
|
|
|
// ---- Dynamic Allocation ----
|
|
int *data = malloc(100 * sizeof(int));
|
|
if (data == NULL) { /* handle */ }
|
|
free(data);
|
|
|
|
// ---- Control Flow ----
|
|
if (x > 0) {
|
|
...
|
|
} else if (x < 0) {
|
|
...
|
|
} else {
|
|
...
|
|
}
|
|
|
|
switch (n) {
|
|
case 0:
|
|
handle_zero();
|
|
break; // Fallthrough only with explicit break
|
|
case 1:
|
|
case 2:
|
|
handle_one_or_two();
|
|
break;
|
|
default:
|
|
handle_other();
|
|
}
|
|
|
|
for (int i = 0; i < 10; i++) { ... }
|
|
while (condition) { ... }
|
|
do { ... } while (condition);
|
|
|
|
// ---- C11/C17 Features ----
|
|
// _Generic (type-generic macro)
|
|
#define ABS(x) _Generic((x), \
|
|
int: abs, \
|
|
long: labs, \
|
|
float: fabsf \
|
|
)(x)
|
|
|
|
// _Alignas / _Alignof (C11)
|
|
_Alignas(16) char aligned_buffer[64];
|
|
|
|
// _Static_assert (C11)
|
|
_Static_assert(sizeof(int) >= 4, "int must be at least 4 bytes");
|
|
|
|
// _Noreturn (C11)
|
|
_Noreturn void fatal_error(const char *msg);
|
|
|
|
// _Thread_local (C11)
|
|
_Thread_local int thread_counter = 0;
|
|
|
|
--- 3.5 C++ Syntax (C++20) ----------------------------------------------
|
|
|
|
// ---- auto & Type Deduction ----
|
|
auto x = 42; // int
|
|
auto y = 3.14; // double
|
|
auto z = std::vector{1, 2, 3}; // std::vector<int>
|
|
|
|
// ---- constexpr / consteval / constinit ----
|
|
constexpr int factorial(int n) {
|
|
return n <= 1 ? 1 : n * factorial(n - 1);
|
|
}
|
|
constexpr int f5 = factorial(5); // Computed at compile time
|
|
|
|
consteval int square(int n) { // C++20: must be compile-time
|
|
return n * n;
|
|
}
|
|
|
|
constinit static int counter = 0; // C++20: zero-init at compile time, mutable
|
|
|
|
// ---- Initialization (Uniform / Brace) ----
|
|
int a{42};
|
|
std::vector<int> v{1, 2, 3, 4};
|
|
struct Point { int x; int y; };
|
|
Point p{.x = 10, .y = 20}; // Designated initializer (C++20)
|
|
|
|
// ---- References ----
|
|
int original = 10;
|
|
int& ref = original; // L-value reference
|
|
int&& rref = 42; // R-value reference
|
|
|
|
// ---- Range-based for ----
|
|
for (const auto& item : v) {
|
|
std::println("{}", item);
|
|
}
|
|
|
|
// ---- Lambdas ----
|
|
auto square = [](int n) -> int { return n * n; };
|
|
|
|
// Capture by value, mutable
|
|
auto counter = [count = 0]() mutable { return ++count; };
|
|
|
|
// Capture by reference
|
|
int total = 0;
|
|
std::for_each(v.begin(), v.end(), [&total](int n) { total += n; });
|
|
|
|
// Generic lambda (C++14)
|
|
auto generic = [](const auto& a, const auto& b) { return a + b; };
|
|
|
|
// Template lambda (C++20)
|
|
auto templ = []<typename T>(const std::vector<T>& vec) -> size_t {
|
|
return vec.size();
|
|
};
|
|
|
|
// ---- Classes ----
|
|
class AudioClip {
|
|
public:
|
|
AudioClip(std::string path, int rate = 44100)
|
|
: m_path(std::move(path)), m_sampleRate(rate) {}
|
|
|
|
auto duration() const -> std::chrono::milliseconds;
|
|
|
|
// Defaulted / deleted
|
|
AudioClip(const AudioClip&) = default;
|
|
AudioClip& operator=(const AudioClip&) = delete;
|
|
|
|
// Spaceship operator (C++20)
|
|
auto operator<=>(const AudioClip&) const = default;
|
|
|
|
private:
|
|
std::string m_path;
|
|
int m_sampleRate;
|
|
};
|
|
|
|
// ---- Inheritance & Virtual ----
|
|
class Shape {
|
|
public:
|
|
virtual ~Shape() = default;
|
|
virtual auto area() const -> double = 0; // Pure virtual
|
|
};
|
|
|
|
class Circle final : public Shape {
|
|
public:
|
|
explicit Circle(double r) : m_radius(r) {}
|
|
auto area() const -> double override { return 3.14159 * m_radius * m_radius; }
|
|
private:
|
|
double m_radius;
|
|
};
|
|
|
|
// ---- Templates ----
|
|
template <typename T>
|
|
concept Numeric = std::is_arithmetic_v<T>; // C++20 concept
|
|
|
|
template <Numeric T>
|
|
[[nodiscard]] auto sum(const std::vector<T>& values) -> T {
|
|
T total{};
|
|
for (const auto& v : values) total += v;
|
|
return total;
|
|
}
|
|
|
|
// Variadic templates
|
|
template <typename... Args>
|
|
void log(Args&&... args) {
|
|
(std::println("{}", std::forward<Args>(args)), ...); // Fold expression (C++17)
|
|
}
|
|
|
|
// Template specialization
|
|
template <typename T> struct TypeName { static const char* get() { return "unknown"; } };
|
|
template <> struct TypeName<int> { static const char* get() { return "int"; } };
|
|
template <> struct TypeName<double> { static const char* get() { return "double"; } };
|
|
|
|
// ---- Modules (C++20) ----
|
|
// mymodule.ixx / mymodule.cppm
|
|
export module mymodule;
|
|
|
|
export auto greet() -> std::string { return "Hello from module"; }
|
|
|
|
// Consumer:
|
|
import mymodule;
|
|
|
|
// ---- Coroutines (C++20) ----
|
|
#include <coroutine>
|
|
#include <generator> // std::generator (C++23; implement manually for C++20)
|
|
|
|
// ---- Ranges (C++20) ----
|
|
#include <ranges>
|
|
|
|
auto even_squares(const std::vector<int>& v) {
|
|
return v
|
|
| std::views::filter([](int n) { return n % 2 == 0; })
|
|
| std::views::transform([](int n) { return n * n; });
|
|
}
|
|
|
|
// ---- std::format / std::print (C++20/23) ----
|
|
#include <format>
|
|
auto msg = std::format("Value: {}, Name: {}", 42, "Numbrella");
|
|
std::print("Hello, {}.\n", "World");
|
|
|
|
// ---- Span (C++20) ----
|
|
void process(std::span<const int> data) {
|
|
for (int n : data) { ... }
|
|
}
|
|
std::vector<int> v{1,2,3};
|
|
process(v); // Works with vector, array, C-array
|
|
|
|
// ---- Expected (C++23; or tl::expected / boost::outcome for C++20) ----
|
|
#include <expected> // C++23
|
|
auto divide(double a, double b) -> std::expected<double, std::string> {
|
|
if (b == 0) return std::unexpected("division by zero");
|
|
return a / b;
|
|
}
|
|
|
|
// ---- Attributes ----
|
|
[[nodiscard]] int important_result(); // Warn if return value discarded
|
|
[[maybe_unused]] int x = 0; // Suppress unused warning
|
|
[[likely]] if (fast_path) { ... } // Branch prediction hint (C++20)
|
|
[[unlikely]] if (error_path) { ... } // Branch prediction hint (C++20)
|
|
[[noreturn]] void fatal(); // Function never returns
|
|
|
|
// ---- Three-way comparison (C++20) ----
|
|
struct Version {
|
|
int major, minor, patch;
|
|
auto operator<=>(const Version&) const = default; // auto-generates ==, !=, <, <=, >, >=
|
|
};
|
|
|
|
--- 3.6 STL Quick Reference (C++20) ------------------------------------
|
|
|
|
// Containers
|
|
#include <vector> // Dynamic array
|
|
#include <array> // Fixed-size array
|
|
#include <string> // String (std::string)
|
|
#include <string_view> // Non-owning string view
|
|
#include <map> // Ordered key-value (red-black tree)
|
|
#include <unordered_map> // Hash map
|
|
#include <set> // Ordered set
|
|
#include <unordered_set> // Hash set
|
|
#include <deque> // Double-ended queue
|
|
#include <list> // Doubly-linked list
|
|
#include <forward_list> // Singly-linked list
|
|
#include <stack> // LIFO
|
|
#include <queue> // FIFO
|
|
#include <priority_queue>// Heap
|
|
#include <span> // Non-owning view of contiguous data (C++20)
|
|
#include <optional> // Maybe value
|
|
#include <variant> // Type-safe union
|
|
#include <any> // Type-erased value
|
|
#include <tuple> // Heterogeneous tuple
|
|
#include <bitset> // Bit array
|
|
|
|
// Algorithms
|
|
#include <algorithm> // sort, find, copy, transform, etc.
|
|
#include <numeric> // accumulate, iota, gcd, lcm
|
|
#include <ranges> // Range adaptors (C++20)
|
|
|
|
// Utilities
|
|
#include <memory> // unique_ptr, shared_ptr, make_unique, make_shared
|
|
#include <chrono> // Time utilities
|
|
#include <thread> // Threading
|
|
#include <mutex> // Mutex, lock_guard, scoped_lock
|
|
#include <filesystem> // File system operations
|
|
#include <functional> // std::function, std::bind
|
|
|
|
// I/O
|
|
#include <iostream> // cin, cout, cerr
|
|
#include <fstream> // File I/O
|
|
#include <sstream> // String streams
|
|
#include <print> // std::print, std::println (C++23)
|
|
#include <format> // std::format (C++20)
|
|
|
|
--- 3.7 Smart Pointers & RAII -------------------------------------------
|
|
|
|
// Unique ownership
|
|
auto p1 = std::make_unique<AudioClip>("sound.wav");
|
|
auto p2 = std::move(p1); // Transfer ownership; p1 == nullptr
|
|
|
|
// Shared ownership
|
|
auto s1 = std::make_shared<Config>(100);
|
|
auto s2 = s1; // Reference count = 2
|
|
|
|
// Weak reference (breaks cycles)
|
|
std::weak_ptr<Config> weak = s1;
|
|
if (auto locked = weak.lock()) {
|
|
locked->use();
|
|
}
|
|
|
|
// RAII guard
|
|
{
|
|
std::lock_guard lock(m_mutex); // Auto-locks, auto-unlocks
|
|
shared_data.modify();
|
|
}
|
|
|
|
// Custom deleter
|
|
auto file = std::unique_ptr<FILE, decltype(&fclose)>(
|
|
fopen("data.bin", "rb"), fclose
|
|
);
|
|
|
|
// Scope guard (manual implementation or library)
|
|
template <typename F>
|
|
class ScopeGuard {
|
|
F m_func; bool m_active = true;
|
|
public:
|
|
explicit ScopeGuard(F f) : m_func(std::move(f)) {}
|
|
~ScopeGuard() { if (m_active) m_func(); }
|
|
void dismiss() { m_active = false; }
|
|
ScopeGuard(const ScopeGuard&) = delete;
|
|
ScopeGuard& operator=(const ScopeGuard&) = delete;
|
|
ScopeGuard(ScopeGuard&&) = default;
|
|
ScopeGuard& operator=(ScopeGuard&&) = default;
|
|
};
|
|
// Usage: auto guard = ScopeGuard([] { cleanup(); });
|
|
|
|
--- 3.8 Threading & Atomics ---------------------------------------------
|
|
|
|
// Threads
|
|
#include <thread>
|
|
std::thread t([] { doWork(); });
|
|
t.join(); // Wait for completion
|
|
// Or t.detach() for fire-and-forget
|
|
|
|
// Mutex & condition variable
|
|
std::mutex m;
|
|
std::condition_variable cv;
|
|
bool ready = false;
|
|
|
|
// Producer
|
|
{
|
|
std::lock_guard lk(m);
|
|
ready = true;
|
|
}
|
|
cv.notify_one();
|
|
|
|
// Consumer
|
|
std::unique_lock lk(m);
|
|
cv.wait(lk, [] { return ready; }); // Wait + check predicate
|
|
|
|
// Atomic
|
|
#include <atomic>
|
|
std::atomic<int> counter{0};
|
|
counter.fetch_add(1, std::memory_order_relaxed);
|
|
|
|
// Async / Future
|
|
#include <future>
|
|
auto fut = std::async(std::launch::async, [] { return compute(); });
|
|
auto result = fut.get(); // Blocks until ready
|
|
|
|
// jthread (C++20: auto-joining thread)
|
|
std::jthread jt([](std::stop_token token) {
|
|
while (!token.stop_requested()) {
|
|
doWork();
|
|
}
|
|
});
|
|
// jthread auto-joins on destruction; request_stop() cooperatively stops it
|
|
|
|
// Latch / Barrier (C++20)
|
|
#include <latch>
|
|
std::latch done{3}; // Wait for 3 countdowns
|
|
done.count_down();
|
|
done.wait();
|
|
|
|
--- 3.9 Move Semantics --------------------------------------------------
|
|
|
|
class Buffer {
|
|
public:
|
|
Buffer(size_t size) : m_data(std::make_unique<char[]>(size)), m_size(size) {}
|
|
|
|
// Move constructor
|
|
Buffer(Buffer&& other) noexcept
|
|
: m_data(std::move(other.m_data)), m_size(other.m_size) {
|
|
other.m_size = 0;
|
|
}
|
|
|
|
// Move assignment
|
|
Buffer& operator=(Buffer&& other) noexcept {
|
|
if (this != &other) {
|
|
m_data = std::move(other.m_data);
|
|
m_size = other.m_size;
|
|
other.m_size = 0;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
// Delete copy (move-only type)
|
|
Buffer(const Buffer&) = delete;
|
|
Buffer& operator=(const Buffer&) = delete;
|
|
|
|
private:
|
|
std::unique_ptr<char[]> m_data;
|
|
size_t m_size = 0;
|
|
};
|
|
|
|
Buffer create() {
|
|
Buffer b{1024};
|
|
return b; // NRVO / move (compiler-elided or moved)
|
|
}
|
|
Buffer sink = create(); // Move or copy elision
|
|
|
|
--- 3.10 LLVM IR Basics --------------------------------------------------
|
|
|
|
// ---- What is LLVM IR? ----
|
|
// LLVM Intermediate Representation is a low-level, platform-independent,
|
|
// Static Single Assignment (SSA) language used between the Clang frontend
|
|
// and the LLVM backend optimizer/code-generator.
|
|
|
|
// ---- Generating IR ----
|
|
// clang++ -std=c++20 -S -emit-llvm source.cpp -o source.ll (text)
|
|
// clang++ -std=c++20 -c -emit-llvm source.cpp -o source.bc (bitcode)
|
|
|
|
// ---- Minimal .ll Example (hand-written equivalent of a C function) ----
|
|
|
|
; Module-level
|
|
target triple = "x86_64-unknown-linux-gnu"
|
|
|
|
; @.str = private unnamed_addr constant [14 x i8] c"Hello, %d!\0A\00"
|
|
|
|
declare i32 @printf(i8*, ...)
|
|
|
|
; define i32 @main() #0 {
|
|
; entry:
|
|
; %call = call i32 (i8*, ...) @printf(i8* getelementptr (...), i32 42)
|
|
; ret i32 0
|
|
; }
|
|
|
|
// ---- Key LLVM IR Concepts ----
|
|
//
|
|
// SSA (Static Single Assignment):
|
|
// Every virtual register is assigned exactly once.
|
|
// %result = add i32 %a, %b ← %result can never be re-assigned.
|
|
//
|
|
// Basic Blocks:
|
|
// A straight-line sequence of instructions ending with a terminator
|
|
// (br, ret, switch, etc.). Labels mark block entry points.
|
|
//
|
|
// PHI Nodes:
|
|
// Merge SSA values from different predecessor blocks.
|
|
// %val = phi i32 [ %then_val, %then_block ], [ %else_val, %else_block ]
|
|
//
|
|
// Types:
|
|
// i1, i8, i16, i32, i64 ← Integer types
|
|
// float, double ← FP types
|
|
// ptr ← Opaque pointer (LLVM ≥ 15)
|
|
// [N x T] ← Array
|
|
// { T1, T2, ... } ← Struct
|
|
// <N x T> ← Vector
|
|
|
|
// ---- LLVM Toolchain ----
|
|
//
|
|
// llc — Compile .ll/.bc to native assembly
|
|
// lli — JIT-execute .ll/.bc directly
|
|
// opt — LLVM optimizer (run passes on IR)
|
|
// llvm-link — Link multiple .bc files into one
|
|
// llvm-dis — Disassemble .bc → .ll (human-readable)
|
|
// llvm-as — Assemble .ll → .bc
|
|
// llvm-ar — Archive .bc files
|
|
// llvm-nm — List symbols in .bc files
|
|
// llvm-objdump — Dump object information
|
|
// clang — Frontend (C → IR, C++ → IR, IR → native)
|
|
|
|
// ---- Optimization Pipeline (opt) ----
|
|
// opt -O2 input.ll -o output.ll
|
|
// opt -passes="default<O2>" input.ll -o output.ll (new PM syntax)
|
|
|
|
// ---- Linking IR ----
|
|
// llvm-link a.bc b.bc -o combined.bc
|
|
// clang++ combined.bc -o program
|
|
|
|
// ---- LTO with Clang ----
|
|
// Compile: clang++ -flto=thin -c a.cpp b.cpp → a.o, b.o (contain bitcode)
|
|
// Link: clang++ -flto=thin a.o b.o -o program
|
|
|
|
// ---- Writing a simple LLVM pass (skeleton) ----
|
|
// #include "llvm/Pass.h"
|
|
// #include "llvm/IR/Function.h"
|
|
// struct MyPass : public llvm::FunctionPass {
|
|
// static char ID;
|
|
// MyPass() : FunctionPass(ID) {}
|
|
// bool runOnFunction(Function &F) override {
|
|
// // Inspect/transform F
|
|
// return false; // true if modified
|
|
// }
|
|
// };
|
|
// char MyPass::ID = 0;
|
|
// static RegisterPass<MyPass> X("mypass", "My Analysis Pass");
|
|
|
|
// ---- Clang Attributes for LLVM IR Control ----
|
|
[[gnu::noinline]] void dont_inline_me(); // Suppress inlining
|
|
[[gnu::always_inline]] inline void must_inline_me();
|
|
__attribute__((optnone)) void debug_me(); // Disable optimization for this function
|
|
|
|
// ---- Clang Builtins for low-level access ----
|
|
__builtin_expect(cond, 0); // Branch prediction hint
|
|
__builtin_prefetch(ptr); // Prefetch hint
|
|
__builtin_assume(cond); // Optimization assumption
|
|
__builtin_unreachable(); // Mark unreachable code
|
|
|
|
// ---- Compiler Explorer pattern ----
|
|
// https://godbolt.org — paste code, see generated LLVM IR / assembly
|
|
// Useful flags: -std=c++20 -O2 -march=native
|
|
|
|
--- 3.11 Common Clang Attributes & Pragmas -------------------------------
|
|
|
|
// ---- Function attributes ----
|
|
[[nodiscard]] int compute(); // C++17: warn if result unused
|
|
[[deprecated("Use newAPI() instead")]] void oldAPI();
|
|
[[noreturn]] void fatal_exit();
|
|
|
|
// ---- Clang-specific attributes ----
|
|
__attribute__((constructor)) void on_load(); // Run before main()
|
|
__attribute__((destructor)) void on_unload(); // Run after main() / atexit
|
|
__attribute__((used)) void keep_symbol(); // Prevent removal even if unused
|
|
__attribute__((visibility("default"))) void exported_func();
|
|
__attribute__((visibility("hidden"))) void internal_func();
|
|
__attribute__((aligned(16))) char buffer[64];
|
|
__attribute__((packed)) struct Compact { char a; int b; };
|
|
|
|
// ---- Compiler barriers ----
|
|
asm volatile("" ::: "memory"); // Full compiler barrier
|
|
__sync_synchronize(); // Full memory fence
|
|
|
|
// ---- SIMD pragmas ----
|
|
#pragma clang loop vectorize(enable)
|
|
for (int i = 0; i < N; i++) { ... }
|
|
|
|
#pragma clang loop unroll(enable)
|
|
for (int i = 0; i < 4; i++) { ... }
|
|
|
|
===============================================================================
|
|
END OF SYNTAX GUIDE
|
|
=============================================================================== |