BobShit — référence développeur
BobShit est un langage de programmation interprété, conçu pour être
humain-first : syntaxe lâche, keywords bilingues (FR/EN), et un mode soft qui
absorbe une bonne partie des typos. Les sources portent l’extension
.shit.
lang/). Le playground web
embarque un interpréteur JS miroir pour exécuter sans toolchain.
Philosophy / soft mode
La plupart des langages te jettent une erreur fatale dès qu’une parenthèse manque. BobShit part du principe inverse : si l’intention est claire, on exécute. En mode soft (défaut) :
- parenthèses optionnelles autour des conditions
if/while then/dooptionnels- virgules optionnelles dans
say a bet parfois dans les listes - string non fermée → on ferme implicitement en fin de ligne / fichier
- identifiant inconnu →
nil(au lieu d’exploser) - division par zéro →
0(pas de NaN drama) - caractères junk ignorés avec warning côté CLI
# ça passe en soft
x=1+ 2
say "x =" x
if x>2
say "ok"
end
CLI strict : bobshit -s file.shit (moins indulgent).
Install & CLI
Téléchargement officiel v0.1.1 : github.com/Riric65/bobshit — paquets Linux (deb/rpm/Arch), Windows setup, macOS, tarballs. Voir aussi la page download.
# Debian / Ubuntu
sudo apt install ./bobshit_0.1.1_amd64.deb
# Fedora / RHEL
sudo dnf install ./bobshit-0.1.1-1.x86_64.rpm
# Linux générique
tar xzf bobshit-0.1.1-linux-x86_64.tar.gz
sudo install -m755 bobshit /usr/local/bin/
# Depuis les sources
git clone https://github.com/Riric65/bobshit.git
cd bobshit/lang && make
./bobshit examples/hello.shit
./bobshit -e 'say "hi", 1+1'
./bobshit -i # REPL
./bobshit -s file.shit # strict
./bobshit --gc jeu.shit # GC opt-in (0.1.1)
./bobshit --hold file.shit
./bobshit --ast file.shit
./bobshit --tokens file.shit
Dépendances pour compiler : gcc/clang C11 + libm.
Aucune autre lib. Binaire : bobshit.
Hello world
# hello.shit
say "salut, c'est BobShit"
name = "Bob"
say "moi c'est", name
Lexing & comments
Commentaires supportés :
# ligne// ligne/* bloc */
Les newlines agissent comme séparateurs soft (pas besoin de ;).
Les keywords sont case-insensitive.
Types
Types runtime :
nil— absence de valeur (null,none,rien)bool—true/false(aussivrai/faux)num— flottant double (entiers affichés sans décimales)str— chaînes Unicode (UTF-8 côté C, JS strings côté web)list— tableaux dynamiques[1, 2, 3]map— objets{key: value}fun/native— fonctions utilisateur ou builtins
say type(42) # num
say type("yo") # str
say type([1,2]) # list
say type({a:1}) # map
say type(nil) # nil
Truthiness : nil, false, 0, "", list/map vides → falsy.
Tout le reste → truthy.
Variables
x = 10
x = x + 1
name := "bob" # := aussi accepté
compteur = 0
Lookup case-insensitive : Foo et foo désignent la même binding
dans un scope. Assignation crée la variable si elle n’existe pas (pas de
let/var obligatoire).
Operators
+ - * / %
== != < > <= >=
and / && or / || not / !
+sur strings → concat+list + list → concat ; list + item → push copy- arithmétique soft coerce via
num-ish parsing and/orshort-circuit
say "bob" + "shit" # bobshit
say [1,2] + [3] # [1,2,3]
say 10 / 0 # 0 (soft)
say true and false # false
say 1 or 0 # 1
Strings
Quotes simples ou doubles. Escapes : \n \t \r \\.
s = "ligne1\nligne2"
say s[0] # index caractère
say len(s)
say upper(s)
say lower("BOB")
say split("a,b,c", ",")
say join(["a","b"], "-")
Lists & maps
xs = [10, 20, 30]
say xs[0]
xs[1] = 99
push(xs, 40)
say pop(xs)
user = {name: "Xem", score: 42}
say user.name
say user["score"]
user.level = 3
say keys(user)
say has(user, "name")
Index négatif à la Python : xs[-1] → dernier élément.
Dot access obj.key est du sucre pour obj["key"].
if / elif / else
if n > 10 then
say "grand"
elif n > 5
say "moyen"
else
say "petit"
end
# FR
si n == 0 alors
say "zéro"
fin
Blocs fermés par end / fin / } / done.
then/do optionnels. Parenthèses autour de la condition optionnelles.
while / for / foreach
# while
i = 0
while i < 3
say i
i = i + 1
end
# range for
for i in 1 to 5
say i
end
for i in 0 to 10 step 2
say i
end
# foreach
for x in [1, 2, 3]
say x * x
end
for c in "bob"
say c
end
Alias FR : pour, tantque, dans, jusqua, pas.
break / continue
for i in 1 to 100
if i == 5 then break end
if i % 2 == 0 then continue end
say i
end
Alias : casse/stop, suivant.
try / catch
try
boom = unknown_call()
catch err
say "caught:", err
end
Utile surtout en mode strict. En soft, beaucoup d’erreurs deviennent des
nil silencieux — wrappe les zones critiques si tu veux du feedback.
Defining fun
fun add(a, b)
return a + b
end
# parenthèses optionnelles sur les params
fun add a b
return a + b
end
# alias: fn / def / fonction / func
fonction greet name
say "yo", name
fin
Calling & return
say add(2, 3)
result = add(10, 5)
return # renvoie nil
return 42
# FR: retour / renvoie
Args en trop → ignorés. Args manquants → nil.
Les fonctions capturent leur environnement lexical (closures light).
Recursion
fun factorial n
if n <= 1 then return 1 end
return n * factorial(n - 1)
end
say factorial(6)
Guard anti stack overflow ~256 frames.
say / input / print
say "hello", 1, true
print "alias de say"
affiche "FR alias"
# CLI only (stdin)
name = input("ton nom? ")
say "salut", name
Sur le playground web, input est stubbé (pas de prompt natif) —
utilise des variables hardcodées pour les démos interactives.
Builtins reference
| Name | Signature | Notes |
|---|---|---|
len | len(x) | str / list / map |
type | type(x) | nom de type string |
str | str(x) | stringify |
num/int | num(x) | coerce nombre |
push | push(list, v) | mutates list |
pop | pop(list) | last item |
has | has(obj, key) | map ou list |
keys | keys(map) | list de clés |
abs/floor/ceil | math | — |
min/max | variadic | — |
range | range(a,b,step?) | list inclusive |
join/split | strings | — |
upper/lower | strings | — |
input | input(prompt?) | CLI stdin |
insert/remove | list | mutate list |
reverse/sort | list | in-place |
values/del | map | — |
sum/index/count | — | — |
trim/replace/starts/ends | strings | — |
round/sqrt/pow | math | — |
gc/gc_on/gc_off/gc_stats | mémoire | nouveau 0.1.1 |
C architecture
lang/
include/ common.h lexer.h ast.h parser.h value.h eval.h gc.h
src/ common.c lexer.c ast.c parser.c value.c eval.c gc.c main.c
examples/ *.shit
tests/ suite de régression
docs/ LANGUAGE.md
Makefile
- lexer — tokenise, keywords FR/EN, comments, soft junk skip
- parser — recursive descent → AST
- value — tagged union + env chain
- eval — tree-walk interpreter + natives
- gc — mark-and-sweep opt-in (
--gc, depuis 0.1.1) - main — CLI file /
-e/ REPL /--ast/--tokens
Lexer → parser → eval
source .shit
│
▼
lex() → TokenStream*
│
▼
parse_program() → Node* (AST)
│
▼
eval_run() → stdout / side-effects
Pas de bytecode pour v0.1.1 — tree-walk volontairement simple (~4400 lignes C11,
uniquement libm). Playground JS miroir : public/js/bobshit.js.
Garbage collector (0.1.1)
Avant 0.1.1, la mémoire n’était rendue qu’à la sortie du process. Depuis 0.1.1 : mark-and-sweep opt-in (conservateur — garde ce que la pile pointe).
bobshit --gc jeu.shit # collecte au fil de l'eau
bobshit jeu.shit # défaut : tout rendu à la sortie
bobshit --no-gc fichier.shit
affiche gc_stats() # {live, freed, runs, bytes, enabled}
n = gc() # collecte maintenant
gc_on() / gc_off() # depuis le code
Limites runtime : 256 frames d’appels, 1 000 000 itérations de boucle. Détails : LANGUAGE.md §8.7.
Errors & recovery
- Parse soft : invente
nil, skip token junk, continue le programme - Runtime soft : unknown ident →
nil; bad call →nil - Runtime hard : message
runtime error: …+ exit code 1 - Loops : hard cap 1 000 000 itérations
- Call stack : hard cap 256
FR / EN keywords
if/si else/sinon elif/sinon_si then/alors
while/tantque for/pour in/dans to/jusqua step/pas
fun/fn/def/fonction return/retour/renvoie
end/fin/done do/faire try/essaie catch/attrape
say/print/echo/affiche/log
and/et or/ou not/non
true/vrai false/faux nil/null/none/rien
Grammar sketch (informal)
program := stmt*
stmt := if | while | for | fun | return | break | continue
| try | say | assign | expr
assign := (ident | index) '=' expr
expr := or
or := and (('or'|'||') and)*
and := cmp (('and'|'&&') cmp)*
cmp := add (('=='|'!='|'<'|'>'|'<='|'>=') add)*
add := mul (('+'|'-') mul)*
mul := unary (('*'|'/'|'%') unary)*
unary := ('!'|'-') unary | postfix
postfix := primary (call | index | dot)*
primary := NUM | STR | BOOL | NIL | IDENT | list | map | '(' expr ')'
Recipes
FizzBuzz
for i in 1 to 20
if i % 15 == 0 then say "FizzBuzz"
elif i % 3 == 0 then say "Fizz"
elif i % 5 == 0 then say "Buzz"
else say i
end
end
Map / filter style
fun filter_even xs
out = []
for x in xs
if x % 2 == 0 then push(out, x) end
end
return out
end
say filter_even(range(1, 10))
Config map
cfg = {
host: "bob.xem.yt",
port: 443,
soft: true
}
if cfg.soft then say "running soft on", cfg.host end
FAQ
Pourquoi « Shit » ? Parce que le code humain est du shit, et c’est ok. Le langage est là pour absorber le chaos, pas pour te moraliser.
C’est prod-ready ? C’est une v0.1.1 jouable : runtime C, playground, docs,
GC opt-in (--gc). Pas de modules, pas de threads. Perfect pour scripts & fun.
Où télécharger ? github.com/Riric65/bobshit (release v0.1.1).
Où tester ? Playground ou le binaire C.
Doc complète ? LANGUAGE.md (référence runtime).
Extension ? Toujours .shit. Point final.
BobShit v0.1.1 · GitHub · bob.xem.yt/bobshit/docs