Sheerpower Logo
I.3  Macros and Blueprints

Macros and Blueprints in Sheerpower

Developers often repeat similar code, leading to redundancy, inconsistencies, and potential bugs. Macros and Blueprints in Sheerpower help reduce this by creating reusable code blocks, improving maintenance and efficiency.

In this tutorial, we will explore two powerful facilities in Sheerpower: Macros and Blueprints. These tools allow developers to generate reusable code structures, making programming more efficient and reducing redundancy.

What are Macros and Blueprints?

Macros are ideal for dynamic expansions where parameters need to be substituted into small, reusable code snippets.

Blueprints are suited for generating larger, structured blocks of code. For example, handling similar logic for customers, clients, and employees with minor variations can be efficiently handled using blueprints.

Key Differences Between Macros and Blueprints

  • Blueprints generate a separate copy of the code for each argument provided in the %generate directive. So, if there are 5 arguments, the blueprint code will be duplicated 5 times, each tailored to one of the arguments.
  • Macros produce only one copy of the macro code, expanding it wherever @macro_name is used. The number of arguments doesn't affect the number of code copies; it just influences how the macro expands at each occurrence of @macro_name.

Collaborative Advantage: Standardizing Code with Macros and Blueprints

In collaborative projects, maintaining consistency is crucial when multiple people contribute to the same codebase. Macros and Blueprints play a key role in standardizing repetitive tasks and logic.

By defining critical code blocks with macros or blueprints, teams can ensure:

  • Consistency: Everyone uses the same logic and structure, preventing errors and inconsistencies throughout the codebase.
  • Reusability: By reusing common code patterns, duplication is minimized, making it easier to implement changes across the project.
  • Optimization: Macros and blueprints streamline the process of adding new features or updates, allowing for smoother and quicker integration.
  • Error Reduction: Standardized code is easier to test, making bugs less likely to go unnoticed.
  • Savings: Overall, faster development and reduced maintenance costs in the long run.

Example: Using Blueprints for Standardized Data Validation

Note: In both blueprints and macros, placeholders are enclosed within "[[" and "]]". This design choice makes them easy to identify within the code.
blueprint validator validate_[[placeholder]] store_[[placeholder]] end blueprint

To generate code:

%generate validator with customer

This approach ensures that all developers follow the same procedure, reducing miscommunication and errors, while improving overall maintainability.

Extending Blueprints

Blueprints can be extended to reuse and add new functionality. When extending a blueprint, new content is appended to or prepended before the base blueprint’s content when generating the final code.

Example of Extending and Prepending Blueprints

Let’s define three blueprints:

  1. A base blueprint
  2. An extended blueprint (appends content)
  3. A prepended blueprint (inserts content before the base)
blueprint base_handler print "init_{placeholder}" end blueprint blueprint extended_handler extends base_handler print "last_{placeholder}" end blueprint blueprint prepended_handler prepends base_handler print "first_{placeholder}" end blueprint

Generating Code from an Extended Blueprint

When you generate code using extended_handler with a specific argument, both the base blueprint and the extended content are included:

%generate extended_handler with customer

Generated output:

init_customer last_customer

Generating Code from a Prepended Blueprint

Similarly, generating code with prepended_handler positions the new content before the base blueprint’s content:

%generate prepended_handler with customer

Generated output:

first_customer init_customer

Benefits of Extending Blueprints

  • Code Reuse: Common logic in the base blueprint is reused while extending functionality where needed.
  • Modular Structure: Encourages a modular approach, making code easier to maintain and expand.
  • Reduced Redundancy: By extending base blueprints, code duplication is avoided, keeping blueprints DRY (Don't Repeat Yourself).

Blueprint Placeholders with Formatting Functions

In addition to the standard [[placeholder]], Sheerpower Blueprints support [[placeholder.function]], allowing developers to manipulate the replacement text using specific formatting functions. These functions can adjust the case of the replacement text as follows:

  1. .lcase – Replaces the placeholder with the lowercase version of the replacement text.
  2. .ucase – Replaces the placeholder with the uppercase version of the replacement text.
  3. .ccase – Replaces the placeholder with the capitalized version (first letter capitalized, the rest in lowercase) of the replacement text.

Example Usage

blueprint handler print "processing_[[placeholder.lcase]]" print "validating_[[placeholder.ucase]]" print "completed_[[placeholder.ccase]]" end blueprint %generate handler with CUSTOMER

Generated Output

processing_customer validating_CUSTOMER completed_Customer

This new functionality allows more flexible handling of placeholder values, helping tailor output to specific formatting requirements.

Key Benefits:

  1. Automatic Formatting: Adjust case formatting without manually changing input data.
  2. Increased Flexibility: Provides more control over how placeholders are replaced in generated code.

Sequence Placeholder Feature for %generate

Overview

The %generate statement in Sheerpower Blueprints supports sequence placeholders, which allows for automatic generation of sequence numbers in blueprint parameters. This feature simplifies handling repetitive elements with distinct names.

How it Works

When a parameter in the %generate statement ends with one or more underscores (_), each underscore acts as a placeholder for a sequence number. The sequence number starts at 1 and increments with each repeated use of the same parameter name.

Example

blueprint handler got$ = got$ + "[[placeholder]], " end blueprint blueprint handlerxx extends handler got$ = got$ + " (extended)" end blueprint got$ = '' %generate handler with age, city, ID %generate handlerxx with ID__, ID__ print got$

Generated output:

AGE, CITY, ID, ID01, ID02, AGEX, (extended)

Key Benefits of Sequence Placeholders

  • Automatic Sequence Generation: No need to manually manage sequence numbers for parameters.
  • Consistency: Ensures consistent, sequential names without redundancy or manual tracking.
  • Extended Usability: Works seamlessly with extended blueprints, ensuring appended or inherited logic still applies.

Macros in SheerPower

Macros in SheerPower enable text substitution at compile time, allowing developers to create concise and reusable code snippets. Macros are expanded dynamically using the @macro_name syntax. Placeholders in macro definitions are marked with [[placeholder]] and can have default values set using the equal sign (=). If a value isn’t provided during expansion, the default value will be used.

Defining Macros

Macros in Sheerpower can be defined in two ways: as single-line or multi-line macros. In this section, we will focus on single-line macros.

Single-Line Macros

Single-line macros allow you to create simple text replacements in your code. These macros are particularly useful for defining constants or shorthand notations that improve code readability and maintainability.

Note: Macros can also be used for conditional compilation. See the Condiional Compilation tutorial.

Syntax

  1. Using the equals sign (=):
    macro macro_name = value
  2. Without an equals sign:
    macro macro_name value
Note:In both single-line and multi-line macros, the value of the macro replaces every instance of @macro_name wherever it appears in the code. Macros are prefixed with @ to make them easily identifiable, which aids in maintaining the code.

Example

macro maxsize = 500 macro maxsize2 500 print 'The maximum size is: '; @maxsize print 'The other size is : '; @maxsize2

Explanation

The macro maxsize is defined with the value 500 using the = form. The macro maxsize2 is defined with the same value but without the = symbol.

Both @maxsize and @maxsize2 will be replaced with 500 during macro expansion. This allows for flexible and concise code, avoiding hard-coding values directly into the program.

Output

The maximum size is: 500 The other size is : 500

Single-line macros are ideal for simple value substitution and are expanded inline during the code execution, making them a powerful tool for reducing redundancy and improving code clarity.

Multi-Line Macros:

macro macro_name print "[[shortname=sysboot]]" print "[[event]] occurred." end macro

Expanding Macros

To expand a macro with placeholders, use the @macro_name syntax followed by a list of placeholder=value pairs in parentheses.

Example:
macro log_event print "[[shortname=sysboot]] - [[event=an event]] occurred." end macro @log_event (shortname=Emergency, event="System Boot") @log_event (event="System Boot") @log_event

Nested Macros

Macros in SheerPower can be nested, allowing one macro to reference another. A macro must be defined before it can be referenced.

Example:
macro two print 'in two' end macro macro one print 'in one' @two end macro @one

When @one is called, it prints "in one" and immediately calls @two, which prints "in two". This ensures efficient code reuse and clean structuring.

Example with Placeholders:

macro age_is = "Your age is [[age=21]] for this project" print @age_is (age=30)

Macro with String Substitution:

macro myname = "Sally Sue" + chr$(ascii("!")) print "This is "; @myname

This prints:

This is Sally Sue!

An Advanced Example with explanations

The macro code below defines two macros in Sheerpower that automate the execution of code and measure how long it takes to run. Let's go through each part step by step.

  1. Macro Definition:
    The mycode macro defines a simple loop that counts from 1 to 10,000,000.
    macro mycode for i=1 to 10_000_000 next i end macro

    This macro does not perform any operations inside the loop, it simply iterates 10 million times.

  2. Timing Macro:
    The time_it macro measures how long the code execution takes. It uses the following steps:
    macro time_it print 'Timing: [[expr]]' start timer [[expr]] print 'elapsed: '; _elapsed end macro

    This macro prints the expression being timed, starts a timer, runs the expression, and then prints the elapsed time.

  3. Macro Invocation:
    The @time_it(expr=@mycode) line calls the time_it macro and passes the mycode macro as an argument. The mycode macro runs inside time_it, and the execution time is printed.
Summary: The time_it macro can be used to measure how long it takes to run any code inside of the mycode macro.

Blueprints in Sheerpower

Blueprints are similar to macros but focus on generating reusable templates for larger code blocks. You use the %generate directive to dynamically replace placeholders in blueprints.

Example of Blueprint Definition

blueprint handler print "do_read_[[placeholder]]" print "do_validate_[[placeholder]]" print "do_store_[[placeholder]]" end blueprint

To generate the code:

%generate handler with customer, client, employee

Generated code for customer:

do_read_customer do_validate_customer do_store_customer

Macros vs. Blueprints: A Comparison

Feature Macros Blueprints Best Use
Use Case Dynamic code generation Structured code generation Macros: Small, repeatable code snippets
Blueprints: Larger, structured logic
Flexibility Small, flexible code blocks Large, predefined code templates Macros: Frequent substitutions
Blueprints: Organizing larger repetitive structures
Shortcut Macro Definition macro macro_name = value Not applicable Macros: Simple constants or values
Macro Expansion @macro_name Not applicable Macros: Concisely expands to a single line or entire block of code.
Macro Expansion with placeholder substitutions @macro_name (placeholder1=value1, placeholder2=value2, etc.) Not applicable Macros: Concise expansions with placeholder substitutions
Code Reusability Dynamic placeholders Customizable placeholders Macros: Best for repetitive patterns
Blueprints: Best for modular templates

Viewing Expanded Macros and Blueprints for Debugging

To help with debugging macros and blueprints, you can view their expanded versions. This feature is especially useful when you need to confirm that the expansions are correct.

Note: To view the expanded versions of any macros or blueprints, you toggle the expanded view using the %expand on and %expand off commands.

%expand on @macro_name %generate blueprintname %expand off

This will display the expanded content of the macro and blueprint during code validation.

Usage:

  1. This feature is enabled when you are validating your code using the Validate option in SPDEV or Visual Studio Code.
  2. The expanded code will be displayed between %expand on and %expand off, helping you ensure that the macros or blueprints are correctly expanding as expected.

When to Use It

Use this feature when:

  1. Debugging or validating your macros and blueprints.
  2. You need to confirm that complex expansions are working as intended.
  3. You want a better understanding of how your code is being generated.

This feature simplifies debugging by providing a clear view of the generated code, making it easier to troubleshoot and validate expansions in your projects.

Source: C:\Sheerpower\sptests\test_macros.spsrc, Line: 139 Blueprint: %generate HANDLERPP o got$ = got$ + "(prepended) " o got$ = got$ + "AGEP, " ---------- Source: C:\Sheerpower\sptests\test_macros.spsrc, Line: 141 Macro: @test_it () o if expected$ <> got$ then o print '?? Macros: Expected '; expected$ o print ' Got '; got$ o delay o end if ----------

Summary: Mastering Macros and Blueprints in Sheerpower empowers developers to write cleaner, more efficient code by minimizing repetition and reducing errors. By leveraging these tools, you streamline your development process, enhance code maintainability, and ensure greater consistency throughout your projects.

As you continue to explore these features, you'll unlock new ways to optimize your workflows and elevate your programming expertise.
Hide Description

    

       


      

Enter or modify the code below, and then click on RUN

Looking for the full power of Sheerpower?
Check out the Sheerpower website. Free to download. Free to use.
Wide screen