Created
February 27, 2026 10:15
-
-
Save Shoozza/48dc797dbcd6294867439d6bebc8a297 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!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