POV-Ray : Newsgroups : povray.pov4.discussion.general : Better #read functionality : Re: Better #read functionality Server Time
15 Nov 2025 06:30:18 EST (-0500)
  Re: Better #read functionality  
From: Bald Eagle
Date: 12 Nov 2025 15:55:00
Message: <web.6914f34c2311edc27f81dbac25979125@news.povray.org>
"What would be required to expose the automatic typing from a #read directive,
so that users could implement conditional processing of files based on the data
type read into a variable?"


Copilot said:

In short: you need a way for SDL authors to observe the concrete runtime type of

exposing either (a) type tags on variables or (b) side‑channel metadata
from #read (or both). Below is a practical, engine‑level design you can
implement with minimal surface area, plus SDL examples showing how creators
would use it.

Goals
Let users branch conditionally after #read based on whether the data was a
number, vector (and how many components), string, etc.
Keep backward compatibility with existing scenes.
Avoid changing how #read parses files unless explicitly asked.
Minimal, low‑risk feature set (recommended)
1) Add a built‑in typeof() (or type()) function


to surface it to SDL.

Proposed return codes (example):

TYPE_FLOAT (aka scalar / DBL)
TYPE_VECTOR2, TYPE_VECTOR3, TYPE_VECTOR4, TYPE_VECTOR5
TYPE_COLOR (optional alias of TYPE_VECTOR5 if you want to distinguish colors)
TYPE_STRING
(Optionally later: TYPE_ARRAY, TYPE_DICTIONARY, TYPE_BOOL aliasing float, etc.)
You can implement typeof() to return an integer enum (most compact and fast for
#switch/#case), and optionally a typestr() that returns a descriptive string for
debugging.

Why this works
#read already assigns a value to the destination variable. With typeof(), user

#read needed.

2) (Optional but useful) Expose vector arity via veclen()
Add veclen(Identifier) that returns 2..5 for vectors (including colors), and 0
or 1 for scalars/strings. This removes ambiguity between VECTOR3 vs COLOR if you


3) (Very small change to #read) Publish last‑read metadata
Provide a reserved, read‑only system variable updated by #read:

__read_type → same code as typeof() would give
__read_components → 0 (string/scalar) or 2..5 (vector arity)
__read_ok → 1 if the last #read succeeded, 0 on EOF/type mismatch
__read_line / __read_col (optional) → position where the read began
This is useful when creators prefer to read into dedicated type‑specific
variables (e.g., a float) but still want to know what was actually encountered.

Back‑compat: These identifiers are reserved and only populated
post‑#read. Existing scenes are unaffected.

Alternative/Complementary APIs

Add a mode that chooses destination type from the input, then stores it:

#read Auto (FH, V_ANY)   // V_ANY adopts the type of the data just read
If next lexeme starts with <, parse vector.



IdentifierAsString is requested.
Then typeof(V_ANY) (or __read_type) lets the user branch.

Why this is optional: You can already achieve conditional processing using the



B) Peek before you read: peek_token(FH) / peek_kind(FH)


peek_kind(FH) returns a token class enum (TOK_STRING, TOK_NUMBER, TOK_LESS,

peek_lexeme(FH) (optional) returns the raw lexeme of the next token.
With this, users can decide how to read without risking consumption or errors.


How creators would use it (SDL patterns)
The examples assume typeof() returns integer codes you define and provide as


Pattern 1: Branch after a normal #read



Plain Text


#declare S_READ = "";   // destination can be reassigned to any type later
#fopen FH "data.txt" read

#read (FH, S_READ)

#if (typeof(S_READ) = TYPE_STRING)
    // process string
#elif (typeof(S_READ) = TYPE_FLOAT)
    // process scalar
#else
    #if (veclen(S_READ) = 3)
        // process <x,y,z> (or color-as-vec3)
    #elseif (veclen(S_READ) = 5)
        // process color/vec5
    #end
#end

#fclose FH
// ***end of code***

Show more lines
Pattern 2: Use read‑metadata (no need to call typeof())



Plain Text


#declare V_ANY = 0;
#read (FH, V_ANY)

#if (__read_type = TYPE_STRING)
    // ...
#elseif (__read_type = TYPE_FLOAT)
    // ...
#else
    #if (__read_components = 3)
        // ...
    #end
#end
// ***end of code***
Pattern 3: Peek, then choose a typed read (no auto‑typing required)



Plain Text


#if (peek_kind(FH) = TOK_STRING)
    #declare S_VAL = "";
    #read (FH, S_VAL)
#elseif (peek_kind(FH) = TOK_LESS)
    #declare V_VAL = < 0.0, 0.0, 0.0 >;
    #read (FH, V_VAL)
#else
    #declare S_NUM = 0.0;
    #read (FH, S_NUM)
#end
// ***end of code***
Engine changes required
Parser/runtime
Expose value type tags already present in the internal variant/union that
represents SDL values.
Implement typeof() (expression evaluator hook). Return an integer code; document
constants for SDL.
Implement veclen() to inspect vector arity from the value payload.
Modify #read directive handler to set the metadata variables (__read_type,

Tokenizer (optional, for peeking)
Add peek_kind() and peek_lexeme() APIs that do non‑consuming lookahead on

Ensure the lexer keeps token class and lexeme accessible (typically already
available for error reporting). If not, add a field to carry the exact text
slice.
SDL surface & docs
Define and document the type enum returned by typeof().
Document semantics:
typeof() works on any identifier bound to a value.
veclen() returns 2..5 for vectors, 0/1 otherwise.
__read_* variables are updated after each #read.
Keep all features gated by #version if you want opt‑in behavior.
Error handling & edge cases
EOF: #read should set __read_ok = 0; others unchanged or set to sentinel values.
Type mismatch (legacy reads): preserve existing error behavior. Metadata can
still be set to what was attempted or left unchanged; document this.
NaN/Inf: classify as TYPE_FLOAT.
Colors: decide whether to unify with VECTOR5 or distinguish as TYPE_COLOR. If
you distinguish, set __read_components = 5 in both cases and let typeof()
disambiguate.
Why this design is safe and powerful
Zero breakage: existing scenes keep working; the new functions/vars are
additive.
Immediate utility: even just typeof() unlocks post‑#read branching.
Granularity: if you add peeking later, scene authors get pre‑read control
without engine auto‑typing changes.
Nice‑to‑have future extensions


"string").


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.