Skip to content

Instantly share code, notes, and snippets.

@Shoozza
Created February 27, 2026 10:15
Show Gist options
  • Select an option

  • Save Shoozza/48dc797dbcd6294867439d6bebc8a297 to your computer and use it in GitHub Desktop.

Select an option

Save Shoozza/48dc797dbcd6294867439d6bebc8a297 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Language Safety Ratings</title>
<link href="https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&family=Bebas+Neue&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--bg: #f0ece4;
--surface: #e8e3da;
--dark: #1a1612;
--ink: #2d2820;
--muted: #8a7f6e;
--accent: #c0392b;
--accent2: #e67e22;
--border: #ccc4b0;
}
body {
background: var(--bg);
color: var(--ink);
font-family: 'Space Mono', monospace;
min-height: 100vh;
padding: 3rem 1.5rem 5rem;
overflow-x: hidden;
}
header {
max-width: 1300px;
margin: 0 auto 3rem;
border-bottom: 3px solid var(--dark);
padding-bottom: 1.5rem;
display: flex;
align-items: flex-end;
justify-content: space-between;
flex-wrap: wrap;
gap: 1rem;
}
h1 {
font-family: 'Bebas Neue', sans-serif;
font-size: clamp(3rem, 8vw, 6rem);
letter-spacing: 0.02em;
line-height: 0.9;
color: var(--dark);
}
h1 span { color: var(--accent); }
.subtitle {
font-size: 0.7rem;
color: var(--muted);
letter-spacing: 0.1em;
text-transform: uppercase;
text-align: right;
line-height: 1.8;
}
.controls { max-width: 1300px; margin: 0 auto 0.75rem; display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; }
.controls-row { max-width: 1300px; margin: 0 auto 1.25rem; display: flex; gap: 0.4rem; flex-wrap: wrap; align-items: center; }
.sticky-controls {
position: sticky;
top: 0;
z-index: 20;
background: var(--bg);
padding: 0.75rem 1.5rem 0.75rem;
margin: 0 -1.5rem 1rem;
border-bottom: 2px solid var(--border);
box-shadow: 0 2px 12px rgba(0,0,0,0.06);
}
.label { font-size: 0.62rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--muted); margin-right: 0.2rem; white-space: nowrap; }
.search-box {
font-family: 'Space Mono', monospace;
font-size: 0.78rem;
padding: 0.5rem 0.85rem;
border: 2px solid var(--dark);
background: white;
color: var(--ink);
outline: none;
width: 220px;
}
.search-box:focus { border-color: var(--accent); }
.filter-btn {
font-family: 'Space Mono', monospace;
font-size: 0.6rem;
padding: 0.38rem 0.65rem;
border: 2px solid var(--dark);
background: transparent;
color: var(--ink);
cursor: pointer;
letter-spacing: 0.05em;
text-transform: uppercase;
transition: all 0.15s;
white-space: nowrap;
}
.filter-btn:hover, .filter-btn.active { background: var(--dark); color: var(--bg); }
.filter-btn.tag-active { background: #16a085; color: white; border-color: #16a085; }
.table-wrap {
max-width: 1300px;
margin: 0 auto;
border: 2px solid var(--dark);
overflow: hidden;
}
.table-scroll {
overflow-x: auto;
max-height: 70vh;
overflow-y: auto;
}
.table-inner { min-width: 1100px; }
table { width: 100%; border-collapse: collapse; font-size: 0.75rem; }
thead { background: var(--dark); color: var(--bg); position: sticky; top: 0; z-index: 10; }
th {
padding: 0.85rem 0.6rem;
text-align: left;
letter-spacing: 0.08em;
text-transform: uppercase;
font-size: 0.58rem;
cursor: pointer;
white-space: nowrap;
user-select: none;
}
th:hover { color: var(--accent2); }
th.sorted-asc::after { content: ' ▲'; color: var(--accent2); }
th.sorted-desc::after { content: ' ▼'; color: var(--accent2); }
td { padding: 0.55rem 0.6rem; border-bottom: 1px solid var(--border); vertical-align: middle; }
tr:last-child td { border-bottom: none; }
tr:hover td { background: rgba(0,0,0,0.03); }
.lang-name { font-weight: 700; font-size: 0.8rem; white-space: nowrap; }
.tier-badge {
display: inline-block;
font-size: 0.56rem;
padding: 0.15rem 0.4rem;
letter-spacing: 0.06em;
text-transform: uppercase;
font-weight: 700;
white-space: nowrap;
}
.tier-formal { background: #1a1612; color: #f0ece4; }
.tier-compile { background: #c0392b; color: white; }
.tier-runtime { background: #e67e22; color: white; }
.tier-dynamic { background: #f39c12; color: white; }
.tier-unsafe { background: #95a5a6; color: white; }
.tier-hardware { background: #7f8c8d; color: white; }
.use-tags { display: flex; flex-wrap: wrap; gap: 0.2rem; min-width: 120px; }
.use-tag {
font-size: 0.52rem;
padding: 0.1rem 0.3rem;
border-radius: 3px;
letter-spacing: 0.04em;
text-transform: uppercase;
font-weight: 700;
white-space: nowrap;
border: 1px solid;
}
.tag-game { background:#ff6b3515; color:#b83215; border-color:#ff6b3540; }
.tag-web { background:#05966915; color:#059669; border-color:#05966940; }
.tag-mobile { background:#7c3aed15; color:#7c3aed; border-color:#7c3aed40; }
.tag-desktop { background:#0891b215; color:#0891b2; border-color:#0891b240; }
.tag-server { background:#dc262615; color:#dc2626; border-color:#dc262640; }
.tag-backend { background:#d9770615; color:#b45309; border-color:#d9770640; }
.tag-glue { background:#db277715; color:#db2777; border-color:#db277740; }
.tag-embed { background:#64748b15; color:#475569; border-color:#64748b40; }
.tag-research { background:#6b728015; color:#4b5563; border-color:#6b728040; }
.tag-hardware { background:#92400e15; color:#92400e; border-color:#92400e40; }
.tag-systems { background:#1e3a5f15; color:#1e3a5f; border-color:#1e3a5f40; }
.tag-data { background:#0f766e15; color:#0f766e; border-color:#0f766e40; }
.tag-scripting{ background:#78350f15; color:#78350f; border-color:#78350f40; }
.dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; flex-shrink: 0; }
.dot-yes { background: #27ae60; }
.dot-part { background: #f39c12; }
.dot-no { background: #e74c3c; }
.check-cell { display: flex; align-items: center; gap: 0.35rem; white-space: nowrap; font-size: 0.68rem; color: var(--muted); }
.total-score { font-family: 'Bebas Neue', sans-serif; font-size: 1.3rem; letter-spacing: 0.05em; }
.legend { max-width: 1300px; margin: 1.5rem auto 0; display: flex; gap: 1rem; flex-wrap: wrap; font-size: 0.65rem; color: var(--muted); letter-spacing: 0.05em; text-transform: uppercase; }
.legend-item { display: flex; align-items: center; gap: 0.35rem; }
.count-label { font-size: 0.68rem; color: var(--muted); margin-left: auto; align-self: center; }
.fav-btn {
background: none;
border: none;
cursor: pointer;
font-size: 1rem;
padding: 0 0.2rem;
line-height: 1;
opacity: 0.25;
transition: opacity 0.15s, transform 0.15s;
}
.fav-btn:hover { opacity: 0.6; transform: scale(1.2); }
.fav-btn.faved { opacity: 1; }
.filter-btn.fav-filter-active { background: #e67e22; color: white; border-color: #e67e22; }
</style>
</head>
<body>
<header>
<h1>Language<br><span>Safety</span><br>Index</h1>
<div class="subtitle">
Rated across 7 dimensions · Click headers to sort<br>
Filter by safety tier · Filter by use-case tag<br>
All scores out of 10
</div>
</header>
<div class="sticky-controls">
<div class="controls">
<input class="search-box" type="text" id="search" placeholder="Search language...">
<button class="filter-btn" id="fav-filter-btn" data-favfilter="true">⭐ Favourites</button>
<span class="count-label" id="count-label"></span>
</div>
<div class="controls-row">
<span class="label">Tier:</span>
<button class="filter-btn active" data-filter="all">All</button>
<button class="filter-btn" data-filter="formal">Formally Verified</button>
<button class="filter-btn" data-filter="compile">Compile-time Safe</button>
<button class="filter-btn" data-filter="runtime">Runtime Safe</button>
<button class="filter-btn" data-filter="dynamic">Dynamic Safe</button>
<button class="filter-btn" data-filter="unsafe">Unsafe</button>
<button class="filter-btn" data-filter="hardware">Hardware</button>
</div>
<div class="controls-row">
<span class="label">Use case:</span>
<button class="filter-btn" data-tag="game">Game</button>
<button class="filter-btn" data-tag="web">Web</button>
<button class="filter-btn" data-tag="mobile">Mobile</button>
<button class="filter-btn" data-tag="desktop">Desktop</button>
<button class="filter-btn" data-tag="server">Server</button>
<button class="filter-btn" data-tag="backend">Backend</button>
<button class="filter-btn" data-tag="glue">Glue</button>
<button class="filter-btn" data-tag="embed">Embedded</button>
<button class="filter-btn" data-tag="systems">Systems</button>
<button class="filter-btn" data-tag="data">Data</button>
<button class="filter-btn" data-tag="scripting">Scripting</button>
<button class="filter-btn" data-tag="research">Research</button>
</div>
</div>
<div class="table-wrap">
<div class="table-scroll">
<table id="lang-table">
<thead>
<tr>
<th style="width:36px"></th>
<th data-col="name">Language</th>
<th data-col="tier">Tier</th>
<th>Use Cases</th>
<th data-col="mem">Memory</th>
<th data-col="type">Type</th>
<th data-col="null">Null</th>
<th data-col="err">Errors</th>
<th data-col="conc">Concurrency</th>
<th data-col="cert">Certifiability</th>
<th data-col="prac">Practicality</th>
<th data-col="total">Total /70</th>
<th data-col="safety">Safety /50</th>
</tr>
</thead>
<tbody id="tbody"></tbody>
</table>
</div>
</div>
<div class="legend">
<div class="legend-item"><span class="dot dot-yes"></span> Strong (7–10)</div>
<div class="legend-item"><span class="dot dot-part"></span> Partial (4–6)</div>
<div class="legend-item"><span class="dot dot-no"></span> Weak (1–3)</div>
</div>
<script>
const langs = [
// FORMALLY VERIFIED
{ name:"Coq", tier:"formal", tags:["research"], mem:10,type:10,null:10,err:10,conc:8, cert:10,prac:2 },
{ name:"Agda", tier:"formal", tags:["research"], mem:10,type:10,null:10,err:10,conc:8, cert:10,prac:2 },
{ name:"Lean / Lean 4", tier:"formal", tags:["research"], mem:10,type:10,null:10,err:10,conc:8, cert:10,prac:3 },
{ name:"Idris 2", tier:"formal", tags:["research"], mem:10,type:10,null:10,err:10,conc:7, cert:9, prac:3 },
{ name:"Idris", tier:"formal", tags:["research"], mem:10,type:10,null:10,err:10,conc:7, cert:9, prac:3 },
{ name:"F* (F-star)", tier:"formal", tags:["research","systems"], mem:10,type:10,null:10,err:10,conc:8, cert:10,prac:3 },
{ name:"Isabelle", tier:"formal", tags:["research"], mem:10,type:10,null:10,err:10,conc:7, cert:10,prac:2 },
{ name:"HOL4", tier:"formal", tags:["research"], mem:10,type:10,null:10,err:10,conc:7, cert:10,prac:2 },
{ name:"PVS", tier:"formal", tags:["research"], mem:10,type:10,null:10,err:10,conc:7, cert:10,prac:2 },
{ name:"TLA+", tier:"formal", tags:["research","systems"], mem:10,type:9, null:10,err:9, conc:10,cert:9, prac:4 },
{ name:"Alloy", tier:"formal", tags:["research"], mem:9, type:9, null:9, err:9, conc:8, cert:8, prac:4 },
{ name:"Dafny", tier:"formal", tags:["research","systems"], mem:10,type:10,null:10,err:10,conc:7, cert:9, prac:5 },
{ name:"Why3", tier:"formal", tags:["research"], mem:10,type:10,null:10,err:10,conc:7, cert:9, prac:3 },
{ name:"ACL2", tier:"formal", tags:["research"], mem:10,type:9, null:10,err:9, conc:7, cert:9, prac:2 },
{ name:"Twelf", tier:"formal", tags:["research"], mem:10,type:10,null:10,err:10,conc:6, cert:8, prac:2 },
{ name:"Cedille", tier:"formal", tags:["research"], mem:10,type:10,null:10,err:10,conc:6, cert:7, prac:1 },
{ name:"SPARK/Ada", tier:"formal", tags:["systems","embed","server"], mem:10,type:10,null:9, err:10,conc:8, cert:10,prac:7 },
{ name:"Lustre/SCADE", tier:"formal", tags:["embed","systems"], mem:9, type:9, null:9, err:9, conc:9, cert:10,prac:5 },
{ name:"Esterel", tier:"formal", tags:["embed","systems"], mem:9, type:9, null:9, err:9, conc:9, cert:9, prac:4 },
// COMPILE-TIME SAFE
{ name:"Rust", tier:"compile", tags:["systems","server","embed","game","desktop","web"], mem:10,type:9,null:9,err:9,conc:10,cert:6,prac:8 },
{ name:"Haskell", tier:"compile", tags:["backend","research","data"], mem:8, type:10,null:9, err:9, conc:7, cert:4, prac:7 },
{ name:"Elm", tier:"compile", tags:["web"], mem:8, type:10,null:10,err:10,conc:7, cert:3, prac:6 },
{ name:"OCaml", tier:"compile", tags:["systems","backend","research"], mem:8, type:9, null:8, err:8, conc:7, cert:4, prac:7 },
{ name:"F#", tier:"compile", tags:["backend","desktop","data"], mem:7, type:9, null:8, err:8, conc:7, cert:4, prac:8 },
{ name:"PureScript", tier:"compile", tags:["web"], mem:8, type:10,null:10,err:9, conc:7, cert:3, prac:5 },
{ name:"Gleam", tier:"compile", tags:["backend","server"], mem:8, type:9, null:9, err:9, conc:8, cert:3, prac:5 },
{ name:"Pony", tier:"compile", tags:["systems","server"], mem:9, type:9, null:9, err:8, conc:10,cert:4, prac:4 },
{ name:"Clean", tier:"compile", tags:["research"], mem:8, type:9, null:9, err:8, conc:7, cert:3, prac:3 },
{ name:"Mercury", tier:"compile", tags:["research","systems"], mem:8, type:10,null:9, err:9, conc:7, cert:4, prac:3 },
{ name:"ATS", tier:"compile", tags:["systems","embed"], mem:10,type:9, null:9, err:9, conc:7, cert:5, prac:3 },
{ name:"Flix", tier:"compile", tags:["research","backend"], mem:7, type:9, null:9, err:9, conc:7, cert:2, prac:4 },
{ name:"Koka", tier:"compile", tags:["research"], mem:8, type:9, null:9, err:9, conc:8, cert:2, prac:4 },
{ name:"Granule", tier:"compile", tags:["research"], mem:9, type:10,null:9, err:9, conc:7, cert:2, prac:2 },
{ name:"Vale", tier:"compile", tags:["systems","game"], mem:9, type:8, null:8, err:8, conc:7, cert:2, prac:3 },
{ name:"Austral", tier:"compile", tags:["systems"], mem:9, type:9, null:9, err:9, conc:7, cert:3, prac:3 },
{ name:"Nelua", tier:"compile", tags:["game","systems","embed"], mem:8, type:8, null:7, err:7, conc:5, cert:2, prac:4 },
{ name:"Ur/Web", tier:"compile", tags:["web","backend"], mem:8, type:10,null:9, err:9, conc:6, cert:2, prac:3 },
{ name:"Lobster", tier:"compile", tags:["game"], mem:7, type:7, null:6, err:6, conc:4, cert:1, prac:5 },
// RUNTIME SAFE
{ name:"Go", tier:"runtime", tags:["server","backend","systems"], mem:8, type:7, null:5, err:8, conc:8, cert:3, prac:9 },
{ name:"Swift", tier:"runtime", tags:["mobile","desktop","backend"], mem:8, type:8, null:8, err:7, conc:6, cert:4, prac:9 },
{ name:"Kotlin", tier:"runtime", tags:["mobile","backend","desktop"], mem:7, type:8, null:8, err:7, conc:6, cert:3, prac:9 },
{ name:"Java", tier:"runtime", tags:["backend","server","desktop","mobile"], mem:7, type:7, null:4, err:7, conc:6, cert:5, prac:9 },
{ name:"C#", tier:"runtime", tags:["desktop","game","backend","mobile"], mem:7, type:8, null:7, err:7, conc:6, cert:4, prac:9 },
{ name:"Scala", tier:"runtime", tags:["backend","data","server"], mem:7, type:8, null:7, err:8, conc:7, cert:3, prac:7 },
{ name:"Scala 3", tier:"runtime", tags:["backend","data","server"], mem:7, type:9, null:8, err:8, conc:7, cert:3, prac:7 },
{ name:"Clojure", tier:"runtime", tags:["backend","data","web"], mem:7, type:6, null:6, err:7, conc:8, cert:2, prac:7 },
{ name:"Erlang", tier:"runtime", tags:["server","backend","embed"], mem:8, type:6, null:7, err:8, conc:10,cert:4, prac:6 },
{ name:"Elixir", tier:"runtime", tags:["backend","server","web"], mem:8, type:6, null:7, err:8, conc:10,cert:3, prac:7 },
{ name:"Dart", tier:"runtime", tags:["mobile","web","desktop"], mem:7, type:8, null:8, err:7, conc:6, cert:2, prac:8 },
{ name:"Groovy", tier:"runtime", tags:["scripting","glue","backend"], mem:6, type:6, null:5, err:6, conc:5, cert:2, prac:7 },
{ name:"Ceylon", tier:"runtime", tags:["backend"], mem:7, type:8, null:7, err:7, conc:6, cert:2, prac:4 },
{ name:"Frege", tier:"runtime", tags:["backend","research"], mem:7, type:9, null:8, err:8, conc:6, cert:2, prac:3 },
{ name:"Eta", tier:"runtime", tags:["backend"], mem:7, type:9, null:8, err:8, conc:6, cert:2, prac:3 },
{ name:"ReasonML", tier:"runtime", tags:["web","backend"], mem:7, type:9, null:8, err:8, conc:6, cert:3, prac:5 },
{ name:"ReScript", tier:"runtime", tags:["web"], mem:7, type:9, null:8, err:8, conc:6, cert:3, prac:6 },
{ name:"Ballerina", tier:"runtime", tags:["backend","server"], mem:7, type:7, null:7, err:8, conc:7, cert:2, prac:5 },
{ name:"Crystal", tier:"runtime", tags:["backend","scripting"], mem:7, type:8, null:7, err:7, conc:6, cert:2, prac:6 },
{ name:"AngelScript", tier:"runtime", tags:["game","embed","scripting"], mem:7, type:8, null:6, err:6, conc:4, cert:2, prac:6 },
{ name:"Hack", tier:"runtime", tags:["web","backend"], mem:6, type:7, null:6, err:6, conc:5, cert:2, prac:6 },
{ name:"Virgil", tier:"runtime", tags:["systems"], mem:7, type:8, null:7, err:7, conc:5, cert:2, prac:4 },
{ name:"Object Pascal", tier:"runtime", tags:["desktop","game","embed"], mem:6, type:7, null:4, err:5, conc:5, cert:5, prac:7 },
{ name:"Haxe", tier:"runtime", tags:["game","web","desktop","mobile"], mem:7, type:8, null:7, err:7, conc:5, cert:2, prac:7 },
// DYNAMIC SAFE
{ name:"Python", tier:"dynamic", tags:["glue","data","backend","scripting","web"], mem:7, type:5, null:5, err:6, conc:4, cert:2, prac:10},
{ name:"Ruby", tier:"dynamic", tags:["backend","web","scripting","glue"], mem:7, type:4, null:4, err:5, conc:4, cert:1, prac:8 },
{ name:"JavaScript", tier:"dynamic", tags:["web","backend","desktop","mobile"], mem:6, type:3, null:3, err:4, conc:5, cert:1, prac:10},
{ name:"TypeScript", tier:"dynamic", tags:["web","backend","desktop","mobile"], mem:6, type:7, null:6, err:5, conc:5, cert:2, prac:9 },
{ name:"Lua", tier:"dynamic", tags:["game","embed","scripting","glue"], mem:6, type:3, null:3, err:4, conc:3, cert:2, prac:8 },
{ name:"PHP", tier:"dynamic", tags:["web","backend"], mem:6, type:4, null:4, err:4, conc:3, cert:1, prac:8 },
{ name:"Perl", tier:"dynamic", tags:["glue","scripting","data"], mem:6, type:3, null:3, err:4, conc:3, cert:1, prac:7 },
{ name:"R", tier:"dynamic", tags:["data","research"], mem:6, type:3, null:3, err:4, conc:3, cert:1, prac:7 },
{ name:"Julia", tier:"dynamic", tags:["data","research","systems"], mem:6, type:5, null:4, err:5, conc:5, cert:1, prac:7 },
{ name:"Racket", tier:"dynamic", tags:["research","scripting","glue"], mem:7, type:5, null:5, err:6, conc:5, cert:2, prac:6 },
{ name:"Scheme", tier:"dynamic", tags:["research","embed"], mem:7, type:4, null:4, err:5, conc:4, cert:2, prac:5 },
{ name:"Common Lisp", tier:"dynamic", tags:["backend","research"], mem:7, type:4, null:4, err:6, conc:4, cert:2, prac:6 },
{ name:"Smalltalk", tier:"dynamic", tags:["desktop","research"], mem:7, type:4, null:4, err:6, conc:4, cert:2, prac:5 },
{ name:"Tcl", tier:"dynamic", tags:["scripting","glue","embed"], mem:6, type:3, null:3, err:4, conc:3, cert:1, prac:6 },
{ name:"Io", tier:"dynamic", tags:["research","embed"], mem:6, type:3, null:3, err:4, conc:4, cert:1, prac:4 },
{ name:"Pharo", tier:"dynamic", tags:["desktop","research"], mem:7, type:4, null:4, err:6, conc:4, cert:2, prac:5 },
{ name:"Rebol", tier:"dynamic", tags:["scripting","glue"], mem:6, type:3, null:3, err:4, conc:3, cert:1, prac:4 },
{ name:"Red", tier:"dynamic", tags:["scripting","desktop"], mem:6, type:4, null:3, err:4, conc:3, cert:1, prac:5 },
{ name:"Ring", tier:"dynamic", tags:["scripting","web"], mem:6, type:3, null:3, err:4, conc:3, cert:1, prac:4 },
{ name:"Factor", tier:"dynamic", tags:["research","scripting"], mem:7, type:4, null:4, err:5, conc:4, cert:1, prac:4 },
{ name:"Raku", tier:"dynamic", tags:["scripting","glue","data"], mem:6, type:5, null:4, err:5, conc:4, cert:1, prac:5 },
{ name:"Janet", tier:"dynamic", tags:["scripting","embed","glue"], mem:6, type:4, null:4, err:5, conc:3, cert:1, prac:5 },
{ name:"Fennel", tier:"dynamic", tags:["game","scripting","embed"], mem:6, type:3, null:3, err:4, conc:3, cert:1, prac:4 },
{ name:"Hy", tier:"dynamic", tags:["scripting","glue"], mem:6, type:3, null:3, err:4, conc:3, cert:1, prac:4 },
{ name:"MoonScript", tier:"dynamic", tags:["game","scripting"], mem:6, type:3, null:3, err:4, conc:3, cert:1, prac:4 },
{ name:"CoffeeScript", tier:"dynamic", tags:["web","scripting"], mem:6, type:3, null:3, err:4, conc:4, cert:1, prac:5 },
{ name:"Prolog", tier:"dynamic", tags:["research","data"], mem:7, type:5, null:6, err:6, conc:5, cert:2, prac:5 },
{ name:"Datalog", tier:"dynamic", tags:["research","data"], mem:8, type:6, null:7, err:7, conc:6, cert:3, prac:4 },
{ name:"GDScript", tier:"dynamic", tags:["game"], mem:7, type:7, null:6, err:6, conc:5, cert:1, prac:8 },
{ name:"Teal", tier:"dynamic", tags:["game","scripting","embed"], mem:6, type:7, null:6, err:5, conc:3, cert:1, prac:6 },
{ name:"Luau", tier:"dynamic", tags:["game","scripting"], mem:6, type:7, null:6, err:5, conc:3, cert:1, prac:7 },
{ name:"Squirrel", tier:"dynamic", tags:["game","embed"], mem:6, type:5, null:4, err:5, conc:3, cert:1, prac:5 },
{ name:"Wren", tier:"dynamic", tags:["game","embed","scripting"], mem:6, type:5, null:4, err:5, conc:3, cert:1, prac:5 },
// UNSAFE
{ name:"C", tier:"unsafe", tags:["systems","embed","server","game"], mem:1, type:4, null:1, err:3, conc:2, cert:6, prac:9 },
{ name:"C++", tier:"unsafe", tags:["systems","game","desktop","embed","server"],mem:2, type:5, null:2, err:4, conc:3, cert:6, prac:9 },
{ name:"Assembly (x86)",tier:"unsafe", tags:["systems","embed"], mem:1, type:1, null:1, err:1, conc:1, cert:5, prac:5 },
{ name:"Assembly (ARM)",tier:"unsafe", tags:["systems","embed"], mem:1, type:1, null:1, err:1, conc:1, cert:5, prac:5 },
{ name:"Fortran", tier:"unsafe", tags:["data","research","systems"], mem:2, type:5, null:2, err:3, conc:3, cert:5, prac:5 },
{ name:"COBOL", tier:"unsafe", tags:["backend","server"], mem:3, type:5, null:2, err:3, conc:2, cert:4, prac:5 },
{ name:"Ada", tier:"unsafe", tags:["systems","embed","server"], mem:6, type:8, null:6, err:6, conc:6, cert:9, prac:6 },
{ name:"Pascal", tier:"unsafe", tags:["desktop","embed","research"], mem:4, type:7, null:3, err:4, conc:3, cert:5, prac:6 },
{ name:"Delphi", tier:"unsafe", tags:["desktop","backend"], mem:5, type:7, null:4, err:5, conc:4, cert:4, prac:7 },
{ name:"D", tier:"unsafe", tags:["systems","backend","game"], mem:5, type:7, null:5, err:6, conc:5, cert:3, prac:6 },
{ name:"Objective-C", tier:"unsafe", tags:["mobile","desktop"], mem:3, type:5, null:2, err:4, conc:3, cert:4, prac:6 },
{ name:"Zig", tier:"unsafe", tags:["systems","embed","game"], mem:6, type:7, null:6, err:8, conc:5, cert:3, prac:6 },
{ name:"Odin", tier:"unsafe", tags:["systems","game"], mem:5, type:7, null:5, err:7, conc:4, cert:2, prac:6 },
{ name:"Nim", tier:"unsafe", tags:["systems","scripting","game","backend"], mem:5, type:7, null:5, err:6, conc:5, cert:2, prac:6 },
{ name:"Beef", tier:"unsafe", tags:["game","systems"], mem:5, type:7, null:4, err:5, conc:4, cert:2, prac:4 },
{ name:"Carp", tier:"unsafe", tags:["systems","embed"], mem:6, type:7, null:5, err:6, conc:4, cert:2, prac:3 },
{ name:"Carbon", tier:"unsafe", tags:["systems","server"], mem:3, type:6, null:3, err:4, conc:3, cert:2, prac:4 },
{ name:"C3", tier:"unsafe", tags:["systems","game","embed"], mem:5, type:6, null:5, err:7, conc:4, cert:2, prac:5 },
{ name:"FreeBasic", tier:"unsafe", tags:["game","desktop","systems"], mem:4, type:5, null:3, err:4, conc:3, cert:2, prac:6 },
{ name:"BlitzMax", tier:"unsafe", tags:["game","desktop"], mem:5, type:5, null:3, err:4, conc:3, cert:1, prac:5 },
{ name:"MISRA-C", tier:"unsafe", tags:["embed","systems"], mem:5, type:6, null:5, err:6, conc:5, cert:9, prac:6 },
{ name:"MISRA-C++", tier:"unsafe", tags:["embed","systems","game"], mem:5, type:7, null:5, err:6, conc:5, cert:9, prac:6 },
{ name:"JSF++ (F-35)", tier:"unsafe", tags:["systems","embed"], mem:6, type:7, null:6, err:7, conc:6, cert:10,prac:4 },
{ name:"AUTOSAR C++14", tier:"unsafe", tags:["systems","embed"], mem:5, type:7, null:5, err:6, conc:5, cert:9, prac:5 },
{ name:"SEI CERT C", tier:"unsafe", tags:["systems","embed","server"], mem:6, type:6, null:5, err:6, conc:5, cert:8, prac:6 },
{ name:"SEI CERT C++", tier:"unsafe", tags:["systems","embed","server"], mem:6, type:7, null:5, err:6, conc:5, cert:8, prac:6 },
{ name:"HIC++", tier:"unsafe", tags:["systems","embed"], mem:5, type:7, null:5, err:6, conc:5, cert:8, prac:5 },
{ name:"C++ Core Guidelines", tier:"unsafe", tags:["systems","desktop","server"], mem:5, type:7, null:5, err:6, conc:5, cert:5, prac:7 },
{ name:"Object Pascal Safe Directives", tier:"unsafe", tags:["desktop","embed","systems"], mem:6, type:7, null:5, err:6, conc:5, cert:5, prac:7 },
{ name:"Delphi Coding Standards", tier:"unsafe", tags:["desktop","backend"], mem:5, type:7, null:5, err:5, conc:4, cert:4, prac:7 },
{ name:"FixInsight+Pascal Analyzer", tier:"unsafe", tags:["desktop","backend","embed"], mem:6, type:7, null:5, err:6, conc:4, cert:5, prac:6 },
// HARDWARE
{ name:"VHDL", tier:"hardware",tags:["hardware"], mem:7, type:8, null:7, err:6, conc:7, cert:7, prac:5 },
{ name:"Verilog", tier:"hardware",tags:["hardware"], mem:5, type:5, null:5, err:4, conc:6, cert:6, prac:5 },
{ name:"SystemVerilog", tier:"hardware",tags:["hardware"], mem:5, type:6, null:5, err:5, conc:6, cert:6, prac:6 },
{ name:"Chisel", tier:"hardware",tags:["hardware"], mem:6, type:7, null:6, err:6, conc:6, cert:5, prac:4 },
{ name:"Clash", tier:"hardware",tags:["hardware","research"], mem:7, type:9, null:8, err:7, conc:7, cert:6, prac:4 },
{ name:"Bluespec", tier:"hardware",tags:["hardware"], mem:7, type:8, null:7, err:7, conc:7, cert:7, prac:4 },
];
const seen = new Set();
const unique = langs.filter(l => { if(seen.has(l.name)) return false; seen.add(l.name); return true; });
const tierColors = {
formal: { cls:'tier-formal', label:'Formally Verified' },
compile: { cls:'tier-compile', label:'Compile-time Safe' },
runtime: { cls:'tier-runtime', label:'Runtime Safe' },
dynamic: { cls:'tier-dynamic', label:'Dynamic Safe' },
unsafe: { cls:'tier-unsafe', label:'Unsafe' },
hardware: { cls:'tier-hardware', label:'Hardware' },
};
const tagLabels = {
game:'Game', web:'Web', mobile:'Mobile', desktop:'Desktop',
server:'Server', backend:'Backend', glue:'Glue', embed:'Embedded',
systems:'Systems', data:'Data', scripting:'Scripting', research:'Research', hardware:'HW'
};
function scoreColor(v) {
if (v >= 8) return '#27ae60';
if (v >= 5) return '#f39c12';
return '#e74c3c';
}
function dotClass(v) { return v>=7 ? 'dot-yes' : v>=4 ? 'dot-part' : 'dot-no'; }
function renderDot(val) { return `<div class="check-cell"><span class="dot ${dotClass(val)}"></span>${val}</div>`; }
function renderTags(tags) {
return `<div class="use-tags">${tags.map(t=>`<span class="use-tag tag-${t}">${tagLabels[t]||t}</span>`).join('')}</div>`;
}
let sortCol='total', sortDir=-1, filterTier='all', filterTag=null, searchVal='', showFavsOnly=false;
const favs = new Set();
function getTotal(l) { return l.mem+l.type+l.null+l.err+l.conc+l.cert+l.prac; }
function getSafety(l) { return l.mem+l.type+l.null+l.err+l.conc; }
function renderTable() {
let data = unique.map(l=>({...l,total:getTotal(l),safety:getSafety(l)}));
if (filterTier !== 'all') data = data.filter(l=>l.tier===filterTier);
if (filterTag) data = data.filter(l=>l.tags.includes(filterTag));
if (searchVal) data = data.filter(l=>l.name.toLowerCase().includes(searchVal.toLowerCase()));
if (showFavsOnly) data = data.filter(l=>favs.has(l.name));
data.sort((a,b)=>{
let av=a[sortCol], bv=b[sortCol];
if (typeof av==='string') return sortDir*av.localeCompare(bv);
return sortDir*(bv-av);
});
document.getElementById('tbody').innerHTML = data.map(l => {
const t=l.total, tc=tierColors[l.tier]||{cls:'tier-dynamic',label:l.tier};
const isFaved = favs.has(l.name);
return `<tr>
<td style="text-align:center"><button class="fav-btn ${isFaved?'faved':''}" data-name="${l.name}" title="Favourite">⭐</button></td>
<td><span class="lang-name">${l.name}</span></td>
<td><span class="tier-badge ${tc.cls}">${tc.label}</span></td>
<td>${renderTags(l.tags)}</td>
<td>${renderDot(l.mem)}</td>
<td>${renderDot(l.type)}</td>
<td>${renderDot(l.null)}</td>
<td>${renderDot(l.err)}</td>
<td>${renderDot(l.conc)}</td>
<td>${renderDot(l.cert)}</td>
<td>${renderDot(l.prac)}</td>
<td><span class="total-score" style="color:${scoreColor(t/7)}">${t}</span></td>
<td><span class="total-score" style="color:${scoreColor(l.safety/5)}">${l.safety}</span></td>
</tr>`;
}).join('');
document.getElementById('count-label').textContent = `${data.length} languages`;
document.querySelectorAll('th[data-col]').forEach(th=>{
th.classList.remove('sorted-asc','sorted-desc');
if(th.dataset.col===sortCol) th.classList.add(sortDir===-1?'sorted-desc':'sorted-asc');
});
// bind fav buttons after render
document.querySelectorAll('.fav-btn').forEach(btn=>{
btn.addEventListener('click',()=>{
const name = btn.dataset.name;
if(favs.has(name)) favs.delete(name); else favs.add(name);
renderTable();
});
});
}
document.querySelectorAll('th[data-col]').forEach(th=>{
th.addEventListener('click',()=>{
if(sortCol===th.dataset.col) sortDir*=-1; else{sortCol=th.dataset.col;sortDir=-1;}
renderTable();
});
});
document.querySelectorAll('.filter-btn[data-filter]').forEach(btn=>{
btn.addEventListener('click',()=>{
document.querySelectorAll('.filter-btn[data-filter]').forEach(b=>b.classList.remove('active'));
btn.classList.add('active');
filterTier=btn.dataset.filter;
renderTable();
});
});
document.querySelectorAll('.filter-btn[data-tag]').forEach(btn=>{
btn.addEventListener('click',()=>{
if(filterTag===btn.dataset.tag){
filterTag=null; btn.classList.remove('tag-active');
} else {
document.querySelectorAll('.filter-btn[data-tag]').forEach(b=>b.classList.remove('tag-active'));
filterTag=btn.dataset.tag; btn.classList.add('tag-active');
}
renderTable();
});
});
document.getElementById('fav-filter-btn').addEventListener('click', btn => {
showFavsOnly = !showFavsOnly;
document.getElementById('fav-filter-btn').classList.toggle('fav-filter-active', showFavsOnly);
renderTable();
});
document.getElementById('search').addEventListener('input',e=>{searchVal=e.target.value;renderTable();});
renderTable();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment