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.4 kB 144 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 (typeof process === "object" && 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 (typeof Deno === "object") { 12 // If we're in Deno, use `stderr` 13 const string = `${grey}${file_line}${reset_color}\n${string_value}\n`; 14 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 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 += "\\u{" + char.charCodeAt(0).toString(16).toUpperCase().padStart(4, "0") + "}"; 37 } else { 38 new_str += char; 39 } 40 } 41 new_str += '"'; 42 return new_str; 43} 44 45function echo$inspectDict(map) { 46 let body = "dict.from_list(["; 47 let first = true; 48 49 let key_value_pairs = []; 50 map.forEach((value, key) => { 51 key_value_pairs.push([key, value]); 52 }); 53 key_value_pairs.sort(); 54 key_value_pairs.forEach(([key, value]) => { 55 if (!first) body = body + ", "; 56 body = body + "#(" + echo$inspect(key) + ", " + echo$inspect(value) + ")"; 57 first = false; 58 }); 59 return body + "])"; 60} 61 62function echo$inspectCustomType(record) { 63 const props = Object.keys(record) 64 .map((label) => { 65 const value = echo$inspect(record[label]); 66 return isNaN(parseInt(label)) ? `${label}: ${value}` : value; 67 }) 68 .join(", "); 69 return props ? `${record.constructor.name}(${props})` : record.constructor.name; 70} 71 72function echo$inspectObject(v) { 73 const name = Object.getPrototypeOf(v)?.constructor?.name || "Object"; 74 const props = []; 75 for (const k of Object.keys(v)) { 76 props.push(`${echo$inspect(k)}: ${echo$inspect(v[k])}`); 77 } 78 const body = props.length ? " " + props.join(", ") + " " : ""; 79 const head = name === "Object" ? "" : name + " "; 80 return `//js(${head}{${body}})`; 81} 82 83function echo$inspect(v) { 84 const t = typeof v; 85 if (v === true) return "True"; 86 if (v === false) return "False"; 87 if (v === null) return "//js(null)"; 88 if (v === undefined) return "Nil"; 89 if (t === "string") return echo$inspectString(v); 90 if (t === "bigint" || t === "number") return v.toString(); 91 if (Array.isArray(v)) return `#(${v.map(echo$inspect).join(", ")})`; 92 if (v instanceof $List) return `[${v.toArray().map(echo$inspect).join(", ")}]`; 93 if (v instanceof $UtfCodepoint) return `//utfcodepoint(${String.fromCodePoint(v.value)})`; 94 if (v instanceof $BitArray) return echo$inspectBitArray(v); 95 if (v instanceof $CustomType) return echo$inspectCustomType(v); 96 if (echo$isDict(v)) return echo$inspectDict(v); 97 if (v instanceof Set) return `//js(Set(${[...v].map(echo$inspect).join(", ")}))`; 98 if (v instanceof RegExp) return `//js(${v})`; 99 if (v instanceof Date) return `//js(Date("${v.toISOString()}"))`; 100 if (v instanceof Function) { 101 const args = []; 102 for (const i of Array(v.length).keys()) args.push(String.fromCharCode(i + 97)); 103 return `//fn(${args.join(", ")}) { ... }`; 104 } 105 return echo$inspectObject(v); 106} 107 108function echo$inspectBitArray(bitArray) { 109 // We take all the aligned bytes of the bit array starting from `bitOffset` 110 // up to the end of the section containing all the aligned bytes. 111 let endOfAlignedBytes = bitArray.bitOffset + 8 * Math.trunc(bitArray.bitSize / 8); 112 let alignedBytes = bitArraySlice(bitArray, bitArray.bitOffset, endOfAlignedBytes); 113 114 // Now we need to get the remaining unaligned bits at the end of the bit array. 115 // They will start after `endOfAlignedBytes` and end at `bitArray.bitSize` 116 let remainingUnalignedBits = bitArray.bitSize % 8; 117 if (remainingUnalignedBits > 0) { 118 let remainingBits = bitArraySliceToInt(bitArray, endOfAlignedBytes, bitArray.bitSize, false, false); 119 let alignedBytesArray = Array.from(alignedBytes.rawBuffer); 120 let suffix = `${remainingBits}:size(${remainingUnalignedBits})`; 121 if (alignedBytesArray.length === 0) { 122 return `<<${suffix}>>`; 123 } else { 124 return `<<${Array.from(alignedBytes.rawBuffer).join(", ")}, ${suffix}>>`; 125 } 126 } else { 127 return `<<${Array.from(alignedBytes.rawBuffer).join(", ")}>>`; 128 } 129} 130 131function echo$isDict(value) { 132 try { 133 // We can only check if an object is a stdlib Dict if it is one of the 134 // project's dependencies. 135 // The `Dict` class is the default export of `stdlib/dict.mjs` 136 // that we import as `$stdlib$dict`. 137 return value instanceof $stdlib$dict.default; 138 } catch { 139 // If stdlib is not one of the project's dependencies then `$stdlib$dict` 140 // will not have been imported and the check will throw an exception meaning 141 // we can't check if something is actually a `Dict`. 142 return false; 143 } 144}