Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

gleam / compiler-core / templates / echo.mjs
5.5 kB 165 lines
1function echo(value, file, line) { 2 const grey = "\u001b[90m"; 3 const reset_color = "\u001b[39m"; 4 const file_line = `${file}:${line}`; 5 const string_value = echo$inspect(value); 6 7 if (globalThis.process?.stderr?.write) { 8 // If we're in Node.js, use `stderr` 9 const string = `${grey}${file_line}${reset_color}\n${string_value}\n`; 10 process.stderr.write(string); 11 } else if (globalThis.Deno) { 12 // If we're in Deno, use `stderr` 13 const string = `${grey}${file_line}${reset_color}\n${string_value}\n`; 14 globalThis.Deno.stderr.writeSync(new TextEncoder().encode(string)); 15 } else { 16 // Otherwise, use `console.log` 17 // The browser's console.log doesn't support ansi escape codes 18 const string = `${file_line}\n${string_value}`; 19 globalThis.console.log(string); 20 } 21 22 return value; 23} 24 25function echo$inspectString(str) { 26 let new_str = '"'; 27 for (let i = 0; i < str.length; i++) { 28 let char = str[i]; 29 if (char == "\n") new_str += "\\n"; 30 else if (char == "\r") new_str += "\\r"; 31 else if (char == "\t") new_str += "\\t"; 32 else if (char == "\f") new_str += "\\f"; 33 else if (char == "\\") new_str += "\\\\"; 34 else if (char == '"') new_str += '\\"'; 35 else if (char < " " || (char > "~" && char < "\u{00A0}")) { 36 new_str += 37 "\\u{" + 38 char.charCodeAt(0).toString(16).toUpperCase().padStart(4, "0") + 39 "}"; 40 } else { 41 new_str += char; 42 } 43 } 44 new_str += '"'; 45 return new_str; 46} 47 48function echo$inspectDict(map) { 49 let body = "dict.from_list(["; 50 let first = true; 51 52 let key_value_pairs = []; 53 map.forEach((value, key) => { 54 key_value_pairs.push([key, value]); 55 }); 56 key_value_pairs.sort(); 57 key_value_pairs.forEach(([key, value]) => { 58 if (!first) body = body + ", "; 59 body = body + "#(" + echo$inspect(key) + ", " + echo$inspect(value) + ")"; 60 first = false; 61 }); 62 return body + "])"; 63} 64 65function echo$inspectCustomType(record) { 66 const props = globalThis.Object.keys(record) 67 .map((label) => { 68 const value = echo$inspect(record[label]); 69 return isNaN(parseInt(label)) ? `${label}: ${value}` : value; 70 }) 71 .join(", "); 72 return props 73 ? `${record.constructor.name}(${props})` 74 : record.constructor.name; 75} 76 77function echo$inspectObject(v) { 78 const name = Object.getPrototypeOf(v)?.constructor?.name || "Object"; 79 const props = []; 80 for (const k of Object.keys(v)) { 81 props.push(`${echo$inspect(k)}: ${echo$inspect(v[k])}`); 82 } 83 const body = props.length ? " " + props.join(", ") + " " : ""; 84 const head = name === "Object" ? "" : name + " "; 85 return `//js(${head}{${body}})`; 86} 87 88function echo$inspect(v) { 89 const t = typeof v; 90 if (v === true) return "True"; 91 if (v === false) return "False"; 92 if (v === null) return "//js(null)"; 93 if (v === undefined) return "Nil"; 94 if (t === "string") return echo$inspectString(v); 95 if (t === "bigint" || t === "number") return v.toString(); 96 if (globalThis.Array.isArray(v)) 97 return `#(${v.map(echo$inspect).join(", ")})`; 98 if (v instanceof $List) 99 return `[${v.toArray().map(echo$inspect).join(", ")}]`; 100 if (v instanceof $UtfCodepoint) 101 return `//utfcodepoint(${String.fromCodePoint(v.value)})`; 102 if (v instanceof $BitArray) return echo$inspectBitArray(v); 103 if (v instanceof $CustomType) return echo$inspectCustomType(v); 104 if (echo$isDict(v)) return echo$inspectDict(v); 105 if (v instanceof Set) 106 return `//js(Set(${[...v].map(echo$inspect).join(", ")}))`; 107 if (v instanceof RegExp) return `//js(${v})`; 108 if (v instanceof Date) return `//js(Date("${v.toISOString()}"))`; 109 if (v instanceof Function) { 110 const args = []; 111 for (const i of Array(v.length).keys()) 112 args.push(String.fromCharCode(i + 97)); 113 return `//fn(${args.join(", ")}) { ... }`; 114 } 115 return echo$inspectObject(v); 116} 117 118function echo$inspectBitArray(bitArray) { 119 // We take all the aligned bytes of the bit array starting from `bitOffset` 120 // up to the end of the section containing all the aligned bytes. 121 let endOfAlignedBytes = 122 bitArray.bitOffset + 8 * Math.trunc(bitArray.bitSize / 8); 123 let alignedBytes = bitArraySlice( 124 bitArray, 125 bitArray.bitOffset, 126 endOfAlignedBytes, 127 ); 128 129 // Now we need to get the remaining unaligned bits at the end of the bit array. 130 // They will start after `endOfAlignedBytes` and end at `bitArray.bitSize` 131 let remainingUnalignedBits = bitArray.bitSize % 8; 132 if (remainingUnalignedBits > 0) { 133 let remainingBits = bitArraySliceToInt( 134 bitArray, 135 endOfAlignedBytes, 136 bitArray.bitSize, 137 false, 138 false, 139 ); 140 let alignedBytesArray = Array.from(alignedBytes.rawBuffer); 141 let suffix = `${remainingBits}:size(${remainingUnalignedBits})`; 142 if (alignedBytesArray.length === 0) { 143 return `<<${suffix}>>`; 144 } else { 145 return `<<${Array.from(alignedBytes.rawBuffer).join(", ")}, ${suffix}>>`; 146 } 147 } else { 148 return `<<${Array.from(alignedBytes.rawBuffer).join(", ")}>>`; 149 } 150} 151 152function echo$isDict(value) { 153 try { 154 // We can only check if an object is a stdlib Dict if it is one of the 155 // project's dependencies. 156 // The `Dict` class is the default export of `stdlib/dict.mjs` 157 // that we import as `$stdlib$dict`. 158 return value instanceof $stdlib$dict.default; 159 } catch { 160 // If stdlib is not one of the project's dependencies then `$stdlib$dict` 161 // will not have been imported and the check will throw an exception meaning 162 // we can't check if something is actually a `Dict`. 163 return false; 164 } 165}