package tiny_languages
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
Small languages from scratch: Scheme, Lisp, Smalltalk-80, Pascal, BASIC, JavaScript, HTML, CSS and more
Install
dune-project
Dependency
Authors
Maintainers
Sources
0.3.6.tar.gz
md5=7c636383d146d30ac6f2fa234a6253c8
sha512=c79f3823c5f8f57e5038eb640d487c61168b84aa07c61999d6622ef9fd0c890e2b03b4c6a7cdbbe9352a49e25dda00ac7bb14693cee8e3d7beeed251351a2af0
doc/src/tiny_languages.lang_asm/Highlight_asm.ml.html
Source file Highlight_asm.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131(* Claude Code * * Copyright (C) 2026 Yoann Padioleau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * (LGPL) as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. *) (* See Highlight_asm.mli *) open Highlight_code (* claude: not $, an immediate's prefix ($_do_divide_error: a use) *) let is_start c = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c = '_' || c = '.' let is_ident c = is_start c || (c >= '0' && c <= '9') let is_digit c = c >= '0' && c <= '9' let strip (s : string) : string = if String.length s > 1 && s.[0] = '_' then String.sub s 1 (String.length s - 1) else s let jumps = [ "jmp"; "ljmp"; "call"; "lcall"; "ret"; "lret"; "iret"; "int"; "loop"; "jz"; "jnz"; "je"; "jne"; "jl"; "jle"; "jg"; "jge"; "jb"; "jbe"; "ja"; "jae"; "jc"; "jnc"; "js"; "jns"; "jecxz"; "jcxz"; "jmpi"; "callf"; "jmpf" ] type tok = { line : int; col : int; text : string; mutable cat : category } let contains_s (s : string) (sub : string) : bool = let n = String.length s and m = String.length sub in let rec go i = i + m <= n && (String.sub s i m = sub || go (i + 1)) in go 0 let analyze (src : string) : analysis = let lines = String.split_on_char '\n' src in (* claude: ARM's assembly comments with @ and writes immediates with # * (mov r0, #0x40); x86's gas comments with # (the ~/ix pass: ARM lines * cut at their immediates) *) let arm = List.exists (fun l -> let t = String.trim l in String.length t > 0 && t.[0] = '@') lines || List.exists (fun l -> contains_s l " @ " || contains_s l "\t@ ") lines in let toks = ref [] in let add line col text cat = toks := { line; col; text; cat } :: !toks in let in_comment = ref false in List.iteri (fun y0 l -> let y = y0 + 1 in let n = String.length l in let i = ref 0 in (* the statement's position: 0 its first word, 1 after its mnemonic *) let first = ref true in while !i < n do let c = l.[!i] in if !in_comment then begin let start = !i in while !i < n && not (!i + 1 < n && l.[!i] = '*' && l.[!i + 1] = '/') do incr i done; if !i < n then (i := !i + 2; in_comment := false); add y start (String.sub l start (!i - start)) Comment end else if c = '/' && !i + 1 < n && l.[!i + 1] = '*' then in_comment := true (* claude: # a comment anywhere (gas's), not only first on a line *) else if c = '|' || c = '!' || (c = '#' && ((not arm) || !first)) || (arm && c = '@') || (c = '/' && !i + 1 < n && l.[!i + 1] = '/') then begin add y !i (String.sub l !i (n - !i)) Comment; i := n end else if c = ';' then (first := true; incr i) else if c = '%' && !i + 1 < n && is_start l.[!i + 1] then begin let s = !i in incr i; while !i < n && is_ident l.[!i] do incr i done; add y s (String.sub l s (!i - s)) Parameter end else if c = '"' || c = '\'' then begin let s = !i in incr i; while !i < n && l.[!i] <> c do incr i done; if !i < n then incr i; add y s (String.sub l s (!i - s)) String end else if is_digit c then begin let s = !i in while !i < n && is_ident l.[!i] do incr i done; (* 1: a numeric label, 1f 1b its uses: not names *) add y s (String.sub l s (!i - s)) Number; if !i < n && l.[!i] = ':' then incr i end else if is_start c then begin let s = !i in while !i < n && is_ident l.[!i] do incr i done; let text = String.sub l s (!i - s) in let j = ref !i in while !j < n && (l.[!j] = ' ' || l.[!j] = '\t') do incr j done; let next = if !j < n then Some l.[!j] else None in if !first && next = Some ':' then (add y s text Def_function; i := !j + 1) (* claude: NAME = value, an assembler's constant: a definition * for the names, but drawn as a constant, not as large as a * label (a file's structure is its labels) *) else if !first && next = Some '=' then (add y s text Constructor; first := false) else if !first then begin add y s text (if text.[0] = '.' then Keyword_module else if List.mem (String.lowercase_ascii text) jumps then Keyword_control else Keyword); first := false end else add y s text Global end else incr i done) lines; let toks = Array.of_list (List.rev !toks) in let triples = Array.map (fun t -> (t.line, t.col, t.text)) toks in (* the file's labels and values, by their text *) let defs = Hashtbl.create 64 in Array.iteri (fun i t -> if (t.cat = Def_function || (t.cat = Constructor && t.col = 0)) && not (Hashtbl.mem defs t.text) then Hashtbl.replace defs t.text i) toks; let binds = Hashtbl.create 64 in let definitions = ref [] and references = ref [] in Array.iteri (fun i t -> match t.cat with | Def_function | Constructor when Hashtbl.find_opt defs t.text = Some i -> Hashtbl.replace binds i i; definitions := definition ~name:(strip t.text) triples i Value 3 :: !definitions | Global -> ( match Hashtbl.find_opt defs t.text with | Some d -> Hashtbl.replace binds i d; t.cat <- (if toks.(d).cat = Constructor then Constructor else Local) | None when t.text.[0] <> '.' -> references := { (reference triples i [] Value) with rname = strip t.text } :: !references | None -> ()) | _ -> ()) toks; { spans = Highlight_code.lines src (Array.to_list (Array.map (fun t -> (t.line, t.col, t.text, t.cat)) toks)); occurrences = occurrences triples binds; definitions = List.rev !definitions; references = List.rev !references; opens = []; includes = []; }
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>