Hone logo
Hone
Problems

Implementing a Simple Macro System in TypeScript

This challenge asks you to build a foundational macro system in TypeScript. Macros allow for code generation at compile-time or runtime, enabling powerful abstractions and reducing boilerplate. You will implement a system that defines and expands simple text-based macros.

Problem Description

Your task is to create a TypeScript module that can:

  1. Define Macros: Allow users to define a macro by associating a macro name (a string) with a template string. The template string can contain placeholders that will be replaced with arguments.
  2. Expand Macros: Given a macro name and a set of arguments, expand the macro by substituting the placeholders in its template with the provided arguments.

Key Requirements:

  • Macro Definition: You need a function or class method to register new macros.
  • Placeholder Syntax: Macros will use a simple placeholder syntax. For this challenge, let's use {{argName}} where argName is the name of the argument to be substituted.
  • Argument Mapping: When expanding a macro, you'll need to map provided arguments to the placeholders in the template. The arguments can be provided as an object where keys match the placeholder names.
  • Error Handling: The system should gracefully handle cases where a macro is not found or if an argument is missing for a placeholder.

Expected Behavior:

  • When a macro is defined, it should be stored internally.
  • When expandMacro is called with a valid macro name and arguments, it should return the expanded string.
  • If a macro name doesn't exist, an appropriate error should be thrown.
  • If a placeholder in the template doesn't have a corresponding argument, an appropriate error should be thrown.

Edge Cases to Consider:

  • Macros with no arguments.
  • Arguments with special characters that might conflict with placeholder syntax (though for this challenge, we'll assume standard string arguments).
  • Nested placeholders (consider this an advanced consideration; for the core challenge, simple direct substitution is sufficient).
  • Empty template strings.

Examples

Example 1:

// Assume a MacroSystem class is implemented
const macroSystem = new MacroSystem();

macroSystem.defineMacro("greet", "Hello, {{name}}! You are {{age}} years old.");

const expanded = macroSystem.expandMacro("greet", { name: "Alice", age: 30 });

// expanded should be: "Hello, Alice! You are 30 years old."

Explanation: The greet macro is defined with placeholders {{name}} and {{age}}. When expanded with { name: "Alice", age: 30 }, these placeholders are replaced with the provided values.

Example 2:

// Assume a MacroSystem class is implemented
const macroSystem = new MacroSystem();

macroSystem.defineMacro("logMessage", "Log: {{message}}");

const expanded = macroSystem.expandMacro("logMessage", { message: "User logged in." });

// expanded should be: "Log: User logged in."

Explanation: A simple logging macro where the {{message}} placeholder is replaced.

Example 3: (Error Case)

// Assume a MacroSystem class is implemented
const macroSystem = new MacroSystem();

macroSystem.defineMacro("welcome", "Welcome, {{user}}!");

try {
    macroSystem.expandMacro("welcome", { userName: "Bob" }); // Missing 'user' argument
} catch (error) {
    // error should indicate a missing argument for 'user'
    console.error(error.message); // e.g., "Missing argument for placeholder 'user' in macro 'welcome'"
}

try {
    macroSystem.expandMacro("nonexistentMacro", { data: "some data" });
} catch (error) {
    // error should indicate macro not found
    console.error(error.message); // e.g., "Macro 'nonexistentMacro' not found."
}

Explanation: This example demonstrates how the system should handle missing arguments and non-existent macros by throwing specific errors.

Constraints

  • The macro names and argument names will be valid JavaScript/TypeScript identifiers (strings without spaces or special characters that would interfere with placeholder parsing, except for the {{}}).
  • Argument values will be strings.
  • The maximum number of registered macros is 100.
  • The maximum length of a macro template string is 1000 characters.
  • The maximum number of arguments for a single macro expansion is 10.

Notes

  • Consider how you will store the defined macros. A Map or an object would be suitable.
  • For placeholder replacement, regular expressions can be very helpful.
  • Think about the structure of your MacroSystem. A class might be a good way to encapsulate the macro definitions and the expansion logic.
  • The core challenge is about string manipulation and basic error handling. You don't need to worry about actual TypeScript code generation or parsing.
Loading editor...
typescript