Skip to content

feat(ufmt): enhance printf functionnalities by adding flags #4136

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 39 commits into
base: master
Choose a base branch
from

Conversation

paulogarithm
Copy link

@paulogarithm paulogarithm commented Apr 14, 2025

Fixes

  • ufmt/printf
    • added flag parsing, such as %.number, %#, %0, and others
    • cf 5d71b3a
    • new features has been tested using unit tests (see tests)

paulogarithm and others added 30 commits April 7, 2025 18:47
* includes gnominers
* includes home
* include pure packages
* reorganise gnominers into submodules
* create the dao submodule
* add the tofix folder with all broken features
* create the minerdao

/!\ DAO DOESNT WORK RN BECAUSE OF CYCLE DEPENDANCIES /!\
* i didnt use subfolders
* add precisision flag ("%.2f")
* add 0 & ' ' flags ("%03d", "% 3d")
* add length parsing (not used rn)
* add # for hex ("%#02x")
* add %i & %X (%i is just %d, %X is big hex)
* change the home
* ass some tests to handle what ive done
* also changed my home page so it displays a number
Format -> FormatRound

because it rounds...
* cause of major issue because it was reading to far
* better messages
* better formatting
* use `p/moun/md` for md formatting in users.gno
@paulogarithm
Copy link
Author

@thehowl done

@paulogarithm paulogarithm changed the title feat(ufmt) & fix(#4109): enhance printf functionnalities by adding flags + fixing gnovm html escape issue feat(ufmt): enhance printf functionnalities by adding flags Apr 14, 2025
@paulogarithm paulogarithm marked this pull request as ready for review April 14, 2025 15:08
@Gno2D2 Gno2D2 added the review/triage-pending PRs opened by external contributors that are waiting for the 1st review label Apr 14, 2025
Copy link

codecov bot commented Apr 14, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

📢 Thoughts on this report? Let us know!

Copy link
Member

@notJoon notJoon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've left a few comments. I would appreciate if you could check them 👍

paulogarithm and others added 5 commits April 15, 2025 10:48
* fix oldLen and oldString that was stored and not
  updated in the precision changed, so it was checking
  the old string instead of the fresh new one
* added tests to handle the special case of %.000000f
@paulogarithm
Copy link
Author

@notJoon i'm done fixing everything 👍 i just need your opinion on something (concerning backward pointer checking usefullness)

@paulogarithm
Copy link
Author

tell me if i need to add anything else !

Copy link
Member

@notJoon notJoon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've confirmed that all the requested changes have been reflected and all tests have passed.

It's a minor point related to policy, but the "resolve conversation" button should not be pressed until the reviewer has checked it. Please refer to this document for more details.

Anyway, except for this, everything else looks good.

remove: review/triage-pending flag

@notJoon notJoon removed the review/triage-pending PRs opened by external contributors that are waiting for the 1st review label Apr 16, 2025
@leohhhn leohhhn moved this from In Progress to In Review in 🧑‍🎓Student contributors Apr 16, 2025
@notJoon
Copy link
Member

notJoon commented Apr 16, 2025

@paulogarithm

Hmm... When using ufmt (especially, using Sprintf function), gas consumption increases causing "out of gas" errors and test failures. The other CI failure issues will likely be resolved with a branch update, but this one seems to require code modifications.

I'll check this problem today. If it's okay, may I modify this code together with you?

@paulogarithm
Copy link
Author

paulogarithm commented Apr 16, 2025

totally fine for me, @notJoon ! but maybe it's because of the maps, so when you'll test, can you try putting the maps in the scope like i did, even if it's more greedy on memory ?

@notJoon
Copy link
Member

notJoon commented Apr 17, 2025

can you try putting the maps in the scope like i did, even if it's more greedy on memory ?

I'm testing by directly checking the gas consumption with txtar. It seems rather than map usage, we also need to improve parts related to memory allocation within the ufmt package overall.

@notJoon
Copy link
Member

notJoon commented Apr 17, 2025

@paulogarithm I couldn't push directly to this PR #4174, so I created a separate PR. Please check it and feel free to cherry-pick if needed. thank you 👍

@Kouteki Kouteki moved this from Triage to In Review in 🧙‍♂️gno.land core team Apr 17, 2025
Copy link
Member

@gfanton gfanton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice ! this is something really welcome !

Could you please update documentation above Sprintf as well as indicating all currently supported flags ? (you can take inspiration from https://pkg.go.dev/fmt)

While we are here we could support padding as well ? (could be done in another PR)

I've tried your code against some go/fmt test code, and the output differs in many formatting cases.

		// advanced int (from go/fmt)
		{"%.d", []any{0}, ""},
		{"%.0d", []any{0}, ""},
		{"% d", []any{12345}, " 12345"},
		{"%+d", []any{12345}, "+12345"},
		{"%+d", []any{-12345}, "-12345"},
		{"%#X", []any{0}, "0X0"},
		{"%x", []any{0x12abcdef}, "12abcdef"},
		{"%X", []any{0x12abcdef}, "12ABCDEF"},
		{"%x", []any{^uint32(0)}, "ffffffff"},
		{"%X", []any{^uint64(0)}, "FFFFFFFFFFFFFFFF"},
		// {"%010d", []any{12345}, "0000012345"},
		// {"%010d", []any{-12345}, "-000012345"}, // weird behaviors

		// advanced float (from go/fmt)
		{"%+.3e", []any{0.0}, "+0.000e+00"},
		{"%+.3e", []any{1.0}, "+1.000e+00"},
		{"%+.3x", []any{0.0}, "+0x0.000p+00"},
		{"%+.3x", []any{1.0}, "+0x1.000p+00"},
		{"%+.3f", []any{-1.0}, "-1.000"},
		{"%+.3F", []any{-1.0}, "-1.000"},
		{"%+.3F", []any{float32(-1.0)}, "-1.000"},
		{"% .3E", []any{-1.0}, "-1.000E+00"},
		{"% .3e", []any{1.0}, " 1.000e+00"},
		{"% .3X", []any{-1.0}, "-0X1.000P+00"},
		{"% .3x", []any{1.0}, " 0x1.000p+00"},
		{"%+.3g", []any{0.0}, "+0"},
		{"%+.3g", []any{1.0}, "+1"},
		{"%+.3g", []any{-1.0}, "-1"},
		{"% .3g", []any{-1.0}, "-1"},
		{"% .3g", []any{1.0}, " 1"},
		// Test sharp flag used with floats.
		{"%#g", []any{1e-323}, "1.00000e-323"},
		{"%#g", []any{-1.0}, "-1.00000"},
		{"%#g", []any{1.1}, "1.10000"},
		{"%#g", []any{123456.0}, "123456."},
		{"%#g", []any{1234567.0}, "1.234567e+06"},
		{"%#g", []any{1230000.0}, "1.23000e+06"},
		{"%#g", []any{1000000.0}, "1.00000e+06"},
		{"%#.0f", []any{1.0}, "1."},
		{"%#.0e", []any{1.0}, "1.e+00"},
		{"%#.0x", []any{1.0}, "0x1.p+00"},
		{"%#.0g", []any{1.0}, "1."},
		{"%#.0g", []any{1100000.0}, "1.e+06"},
		{"%#.4f", []any{1.0}, "1.0000"},
		{"%#.4e", []any{1.0}, "1.0000e+00"},
		{"%#.4x", []any{1.0}, "0x1.0000p+00"},
		{"%#.4g", []any{1.0}, "1.000"},
		{"%#.4g", []any{100000.0}, "1.000e+05"},
		{"%#.4g", []any{1.234}, "1.234"},
		{"%#.4g", []any{0.1234}, "0.1234"},
		{"%#.4g", []any{1.23}, "1.230"},
		{"%#.4g", []any{0.123}, "0.1230"},
		{"%#.4g", []any{1.2}, "1.200"},
		{"%#.4g", []any{0.12}, "0.1200"},
		{"%#.4g", []any{10.2}, "10.20"},
		{"%#.4g", []any{0.0}, "0.000"},
		{"%#.4g", []any{0.012}, "0.01200"},
		{"%#.0f", []any{123.0}, "123."},
		{"%#.0e", []any{123.0}, "1.e+02"},
		{"%#.0x", []any{123.0}, "0x1.p+07"},
		{"%#.0g", []any{123.0}, "1.e+02"},
		{"%#.4f", []any{123.0}, "123.0000"},
		{"%#.4e", []any{123.0}, "1.2300e+02"},
		{"%#.4x", []any{123.0}, "0x1.ec00p+06"},
		{"%#.4g", []any{123.0}, "123.0"},
		{"%#.4g", []any{123000.0}, "1.230e+05"},

Even if minimalist, this library should follow the output of go/fmt to be consistent with Go behaviors. Don't hesitate to follow / copy the fmt library code in Go to match the behavior.

Also i got some weird behaviours from %010d with -12345 -> 0000-12345

I will also check the gas issue. Since many projects import this package, we should take extra precautions regarding performance, but please do not compromise readability.

@@ -170,14 +295,14 @@ func (p *printer) doPrintf(format string, args []any) {
writeString(p, verb, arg)
case 'c':
writeChar(p, verb, arg)
case 'd':
case 'd', 'i':
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

%i doesn't seems to exist in go, I don't think we should port it in gno

Comment on lines +37 to +44
// the different flags
const (
flagHashtag uint8 = 1
flagZero uint8 = 1 << 1
flagMinus uint8 = 1 << 2
flagSpace uint8 = 1 << 3
flagPlus uint8 = 1 << 4
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// the different flags
const (
flagHashtag uint8 = 1
flagZero uint8 = 1 << 1
flagMinus uint8 = 1 << 2
flagSpace uint8 = 1 << 3
flagPlus uint8 = 1 << 4
)
// the different flags
const (
flagHashtag uint8 = 1 << iota
flagZero
flagMinus
flagSpace
flagPlus
)

}
stop := false
for {
x, ok := c2f[runes[*index]]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hiding the reference inside a map complicates readability and performance. Why not use a direct switch case like this:

switch *index {
case '+'
case '-':
...
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
📦 🤖 gnovm Issues or PRs gnovm related 🧾 package/realm Tag used for new Realms or Packages.
Projects
Status: In Review
Status: In Review
Development

Successfully merging this pull request may close these issues.

5 participants